15

e.g. if I run this javascript:

var str = 'hello_world_there';
var parts = str.split('_', 2);

var p1 = parts[0];
var p2 = parts[1];

at the end, p1 contains "hello", and p2 contains "world".

I'd like p1 to contain "hello", and p2 to contain "world_there". i.e. I want p2 to contain the rest of the string, regardless of how many underscores it has (similar to how c#'s String.Split(char[] separator, int count) behaves.

Any workarounds ?

user2864740
  • 60,010
  • 15
  • 145
  • 220
Moe Sisko
  • 11,665
  • 8
  • 50
  • 80

6 Answers6

17
var str = 'hello_world_there';
var parts = str.split('_');

var p1 = parts[0];
var p2 = parts.slice(1).join('_');

This will do an ordinary split, but then merge everything past the first match.

Scimonster
  • 32,893
  • 9
  • 77
  • 89
  • If you split by regex like `str.split(/\s+/)` then change it to `str.split(/(\s+)/)` (e.g. add parenthesis around the whole regex) and then use `slice(2).join("")` instead of `slice(1).join('_')` in the solution above. – Jonas Berlin Mar 22 '21 at 15:06
7

This is slightly different from taking the rest as is, but this was useful in my case:

const [a, ...b] = 'foo/bar/baz'.split('/');
// => a: 'foo', b: ['bar', 'baz']
amiq11
  • 71
  • 1
  • 3
3

Write your own function:

function split(string, delimiter, n) {
    var parts = string.split(delimiter);
    return parts.slice(0, n - 1).concat([parts.slice(n - 1).join(delimiter)]);
}
Blender
  • 289,723
  • 53
  • 439
  • 496
2

Just try with:

var parts = str.split('_', 2);
var p1 = parts.shift();
var p2 = parts.join('_');

or:

var index = str.indexOf('_');
var p1 = str.substr(0, index);
var p2 = str.substr(index + 1);
hsz
  • 148,279
  • 62
  • 259
  • 315
2

For your specific case where you just want two parts, the simplest thing is indexOf and substring:

const index = text.indexOf("_");
const p0 = index === -1 ? text : text.substring(0, index);
const p1 = index === -1 ? "" : text.substring(index + 1);

Live Example:

const text = "hello_world_there";
const index = text.indexOf("_");
const p0 = index === -1 ? text : text.substring(0, index);
const p1 = index === -1 ? "" : text.substring(index + 1);
console.log(`p0 = "${p0}", p1 = "${p1}"`);

I've found I want that often enough I have it in a utility module:

const twoParts = (str, delim = " ") => {
    const index = str.indexOf("_");
    if (index === -1) {
        return [str, ""];
    }
    return [
        str.substring(0, index),
        str.substring(index + delim.length),
    ];
};

But if you wanted to do more than just teh two parts, an approach that doesn't require rejoining the string after the fact would be to use a regular expression with capture groups:

const result = text.match(/^([^_]+)_+([^_]+)_+(.*)$/);
const [_, p0 = "", p1 = "", p2 = ""] = result ?? [];

Live Example:

const text = "hello_world_xyz_there";
const result = text.match(/^([^_]+)_+([^_]+)_+(.*)$/);
const [_, p0 = "", p1 = "", p2 = ""] = result ?? [];
console.log(`p0 = "${p0}", p1 = "${p1}", p2 = "${p2}"`);
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
0

Regexp solution (you can change "|" to other chars e.g. "__" but not to "_")

var [p1,p2] = str.replace(/_/,"|").split("|");

let str = 'hello_world_there'
let [p1,p2] = str.replace(/_/,"|").split("|");

console.log("p1:",p1);
console.log("p2:",p2);
Kamil Kiełczewski
  • 85,173
  • 29
  • 368
  • 345