Really, pretty much what the title says.
Say you have this string:
var theString = \"a=b=c=d\";
Now, when you run theString
I'd use something like this:
function JavaSplit(string,separator,n) {
var split = string.split(separator);
if (split.length <= n)
return split;
var out = split.slice(0,n-1);
out.push(split.slice(n-1).join(separator));
return out;
}
What we're doing here is:
One might reasonably think you could chain all of those calls together, but .push()
mutates an array rather than returning a new one. It's also a bit easier for you to follow this way.
If you want the exact equivalent of the Java implementation (no error checking or guard clauses etc):
function split(str, sep, n) {
var out = [];
while(n--) out.push(str.slice(sep.lastIndex, sep.exec(str).index));
out.push(str.slice(sep.lastIndex));
return out;
}
console.log(split("a=b=c=d", /=/g, 2)); // ['a', 'b', 'c=d']
This has the added benefit of not computing the complete split beforehand, as you mentioned in your question.
Are you looking for something closer to PHP's explode?
Here's a method I've devised:
String.prototype.explode = function(sep, n) {
var arr = this.split(sep, n)
if (arr[n-1] != undefined) arr[n-1] += this.substring(arr.join(' ').length);
return arr;
}
This method splits the string like normal, determines if we've hit our limit, and uses substring
to append the text beyond our last split (we can directly access the offset of the first character beyond the last split by getting the length
of a join
used on the array with any single character as the separator)
This method is used just like split
:
str = 'my/uri/needs/to/be/split';
splitResult = str.split('/', 4);
explodeResult = str.explode('/', 4);
console.log(splitResult);
console.log(explodeResult);
// The following will be written to the console:
// splitResult: ["my", "uri", "needs", "to"]
// explodeResult: ["my", "uri", "needs", "to/be/split"]
And of course, this can be spun as a function too:
function explode(str, sep, n) {
var arr = str.split(sep, n)
if (arr[n-1] != undefined) arr[n-1] += this.substring(arr.join(' ').length);
return arr;
}
str = 'my/uri/needs/to/be/split';
explodeResult = explode(str, '/', 4);
One more possible implementation:
function split(s, separator, limit) {
// split the initial string using limit
var arr = s.split(separator, limit);
// get the rest of the string...
var left = s.substring(arr.join(separator).length + separator.length);
// and append it to the array
arr.push(left);
return arr;
}
Fiddle is here.
The answer from Asad is excellent as it allows for variable length RegExp separators (e.g. /\s+/g
, splitting along any length of whitespace, including newlines). However, there are a couple issues with it.
exec
can return null
and cause it to break. This can happen if the separator does not appear in the input string.The following addresses these two issues:
export function split(input, separator, limit) {
if (!separator.global) {
throw new Error("The split function requires the separator to be global.");
}
const output = [];
while (limit--) {
const lastIndex = separator.lastIndex;
const search = separator.exec(input);
if (search) {
output.push(input.slice(lastIndex, search.index));
}
}
output.push(input.slice(separator.lastIndex));
return output;
}
If you want to do that in less lines and avoiding loops:
const theString = "some=string=with=separators";
const limit = 2;
const parts = theString.split('=', limit);
parts.push(theString.slice(parts.join('').length + limit));