需要的确切解决方案:
function megasplit(toSplit, splitters) {
var splitters = splitters.sorted(function(a,b) {return b.length-a.length});
if (!splitters.length)
return toSplit;
else {
var token = splitters[0];
return toSplit
.split(token)
.map(function(segment) {
return megasplit(segment, splitters.slice(1))
})
.intersperse(token)
.flatten()
.filter(Boolean);
}
}
演示:
> megasplit(
"Go ye away, I want some peace && quiet. & Thanks.",
["Go ", ",", "&&", "&", "."]
)
["Go ", "ye away", ",", " I want some peace ", "&", "&", " quiet", ".", " ", "&", " Thanks", "."]
机械(可重复使用!):
Array.prototype.copy = function() {
return this.slice()
}
Array.prototype.sorted = function() {
var copy = this.copy();
copy.sort.apply(copy, arguments);
return copy;
}
Array.prototype.flatten = function() {
return [].concat.apply([], this)
}
Array.prototype.mapFlatten = function() {
return this.map.apply(this,arguments).flatten()
}
Array.prototype.intersperse = function(token) {
return this.mapFlatten(function(x){return [token,x]}).slice(1)
}
注:
- 这需要进行大量研究才能优雅地完成:
- 事实上,规范要求标记(虽然它们应该留在字符串中)不应该被拆分(否则你会得到
"&", "&"
)。这使得使用reduce
变得不可能,并需要递归。
- 我个人也不会忽略空字符串。我可以理解不想在标记上递归拆分,但我个人会简化函数并使输出像正常的
.split
一样,像["", "Go ", "ye away", ",", " I want some peace ", "&&", " quiet", ".", " ", "&", " Thanks", ".", ""]
- 我应该指出,如果你愿意放松一下要求,这个函数可以从15/20行变成1/3行:
如果按照规范的分割行为,则为1行代码:
Array.prototype.mapFlatten = function() {
...
}
function megasplit(toSplit, splitters) {
return splitters.sorted(...).reduce(function(strings, token) {
return strings.mapFlatten(function(s){return s.split(token)});
}, [toSplit]);
}
如果上面的内容难以理解,这里是3句话概括:
Array.prototype.mapFlatten = function() {
...
}
function megasplit(toSplit, splitters) {
var strings = [toSplit];
splitters.sorted(...).forEach(function(token) {
strings = strings.mapFlatten(function(s){return s.split(token)});
});
return strings;
}