问题
Really, pretty much what the title says.
Say you have this string:
var theString = "a=b=c=d";
Now, when you run theString.split("=")
the result is ["a", "b", "c", "d"]
as expected. And, of course, when you run theString.split("=", 2)
you get ["a", "b"]
, which after reading the MDN page for String#split() makes sense to me.
However, the behavior I'm looking for is more like Java's String#split()
: Instead of building the array normally, then returning the first n elements, it builds an array of the first n-1 matches, then adds all the remaining characters as the last element of the array. See the relevant docs for a better description.
How can I get this effect in Javascript?
I'm looking for the answer with the best performance that works like the Java implementation, though the actual way it works can be different.
I'd post my attempt, but I don't know how to go about writing this at all.
回答1:
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.
回答2:
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:
- Splitting the string entirely
- Taking the first n-1 elements, as described.
- Re-joining the remaining elements.
- Appending them to the array from step 2 and returning.
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.
回答3:
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.
回答4:
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));
回答5:
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);
回答6:
const theString = "a=b=c=d";
const [first, ...rest] = theString.split("=");
const second = rest.join("=")
console.log(first, second)
If you are using ECMA 2015, you just need 2 lines.
回答7:
This my implementation:
String.prototype.splitRemainder = function(delim, count) {
if (typeof delim !== 'string') {
return this.split();
}
if (typeof count !== 'number') {
return this.split(delim);
}
if (count < 2) {
return this.split(delim);
}
count--;
const parts = this.split(delim, count);
const remainder = this.slice(parts.join('').length + count);
if (remainder.length > 0) {
parts.push(remainder);
}
return parts;
}
console.log("dasd asds asds asdasd asdasdas".splitRemainder(" ", 4));
console.log("hello-to-you-too".splitRemainder("-",2));
Note that it is not the most efficient way to implement it. So if you're looking for the most efficient solution this is not it.
来源:https://stackoverflow.com/questions/29998343/limiting-the-times-that-split-splits-rather-than-truncating-the-resulting-ar