首先,您需要向后迭代,以确保您最终不会覆盖先前所做的替换,但是,在我的示例中,这并不重要,因为字符串最终会一次全部重新组装。
// > interpolateOnIndices([[5,9], [23,27]], "eggs eggs spam and ham spam");
// < 'eggs <span>eggs</span> spam and ham <span>spam</span>'
function interpolateOnIndices(indices, string) {
"use strict";
var i, pair, position = string.length,
len = indices.length - 1, buffer = [];
for (i = len; i >= 0; i -= 1) {
pair = indices[i];
buffer.unshift("<span>",
string.substring(pair[0], pair[1]),
"</span>",
string.substring(pair[1], position));
position = pair[0];
}
buffer.unshift(string.substr(0, position));
return buffer.join("");
}
这比带有splice
ing 的示例要好一些,因为它不会创建额外的数组(拼接本身会创建额外的数组)。在其他函数中重复使用映射和创建函数会占用一定的内存,但它的运行速度也不是很快......虽然它有点短。
从理论上讲,在大字符串连接上应该比多个连接更有优势,因为内存分配将进行一次,而不是随后丢弃半生不熟的字符串。当然,所有这些都不需要您关心,除非您正在处理大量数据。
编辑:
因为我手头有太多时间,所以我决定做一个测试,看看如何在更大(但相当现实)的数据集上比较变化,下面是我的测试代码和一些结果......
function interpolateOnIndices(indices, string) {
"use strict";
var i, pair, position = string.length,
len = indices.length - 1, buffer = [];
for (i = len; i >= 0; i -= 1) {
pair = indices[i];
buffer.unshift("<span>",
string.substring(pair[0], pair[1]),
"</span>",
string.substring(pair[1], position));
position = pair[0];
}
buffer.unshift(string.substr(0, position));
return buffer.join("");
}
function indexWrap(indexArr, str) {
var chars = str.split("");
for(var i = 0; i < indexArr.length; i++) {
var indexes = indexArr[i];
if(chars[indexes[0]] && chars[indexes[1]]){
chars.splice(indexes[0], 0, "<span>");
chars.splice(indexes[1], 0, "</span>");
}
}
return chars.join("");
}
function replaceOffset(str, offs, tag) {
tag = tag || "span";
offs.reverse().forEach(
function(v) {
str = str.replace(
new RegExp("(.{" + v[0] + "})(.{" + (v[1] - v[0]) + "})"),
"$1<" + tag + ">$2</" + tag + ">"
);
});
return str;
}
function generateLongString(pattern, times) {
"use strict";
var buffer = new Array(times);
while (times >= 0) {
buffer[times] = pattern;
times -= 1;
}
return buffer.join("");
}
function generateIndices(pattern, times, step) {
"use strict";
var buffer = pattern.concat(), block = pattern.concat();
while (times >= 0) {
block = block.concat();
block[0] += step;
block[1] += step;
buffer = buffer.concat(block);
times -= 1;
}
return buffer;
}
var longString = generateLongString("eggs eggs spam and ham spam", 100);
var indices = generateIndices([[5,9], [23,27]], 100,
"eggs eggs spam and ham spam".length);
function speedTest(thunk, times) {
"use strict";
var start = new Date();
while (times >= 0) {
thunk();
times -= 1;
}
return new Date() - start;
}
speedTest(
function() {
replaceOffset(longString, indices, "span"); },
100); // 1926
speedTest(
function() {
indexWrap(indices, longString); },
100); // 559
speedTest(
function() {
interpolateOnIndices(indices, longString); },
100); // 16
在 amd64 Linux (FC-17) 上针对 V8 (Node.js) 进行了测试。
我没有测试未定义的答案,因为我不想加载那个库,尤其是它对这个测试没有任何用处。我想它会在 andbeyond's 和 elclanrs 的变体之间借用某个地方,尽管更倾向于 elclanrs 的答案。