将字符串与分隔符连接起来的最有效方法是什么
What is the most performant way to concatenate a string with a separator
假设我需要实现一个简单的 join
函数,它接受一个数组和 returns 一个由分隔符分隔的串联元素字符串。 内置方法 Array.prototype.join
的作用。我见过的所有实现都会在开头或结尾产生一个冗余分隔符,因此需要 trim 字符串。
比如我可以这样做:
let s = "";
for (let i=0; i < arr.length; i++) s += sep + arr[i];
// redundant separator at the beginning, need to remove it
s = s.substr(1);
或者像这样:
let s = "";
for (let i=0; i < arr.length; i++) s += arr[i] + sep;
// redundant separator at the end, need to remove it
s = s.slice(0, -1);
有没有更好的方法不产生多余的分隔符?导入该实现应该有效地处理所有情况,如空数组等。
我能想到的一种方法是在循环中放置一个 if
语句来检查它是否是 first/last 元素并且在这种情况下不添加分隔符,但这似乎效率低下。有什么想法吗?
如果您想自己定义它,您可以迭代到 length- 1
。循环后你可以只添加最后一项而不带分隔符。
例子
let arr = [1,2,3,4,5];
let sep = '-';
function customJoin(array, separator) {
if(array.length === 0) {
return '';
}
let s = '';
let length = array.length;
for (let i = 0; i < length - 1; i++) {
s += arr[i] + separator;
}
return s + arr[length - 1];
}
console.log(customJoin(arr, sep));
let s = arr[0] || "";
for (let i=1; i < arr.length; i++) s += sep + arr[i];
添加第一个元素,从第二个开始循环,在前面添加分隔符。
正如您在问题中指出的那样,您可以使用条件仅在需要时附加分隔符,从而无需删除多余的分隔符。问题是,如果您连接两个或三个值,它可能是正确的,但是必须在每个循环迭代中进行测试对于大数组来说成本会很高。
对于第一个元素,您可以检查数组的长度并获取字符串值或空字符串。
然后像 Salketer 在他的 中做的一样循环:
let s = arr.length && arr[0].toString() || '';
for (let i=1; i < arr.length; i++) s += sep + arr[i];
另一种可能的选择是使用递归:
function join(a, separator) {
if (a.length === 0) return '';
function concat(a, n) {
return n > 0 ? concat(a, n - 1) + separator + a[n] : a[n];
}
return concat(a, a.length - 1);
}
一个限制是由于调用堆栈大小限制,它无法处理数万个字符的大字符串。
使用减少:
function join(arr, sep){
if (!arr.length)
return '';
return arr.reduce((a,b) => a + sep + b);
}
console.log(join([1,2],'^'));
假设我需要实现一个简单的 join
函数,它接受一个数组和 returns 一个由分隔符分隔的串联元素字符串。 内置方法 Array.prototype.join
的作用。我见过的所有实现都会在开头或结尾产生一个冗余分隔符,因此需要 trim 字符串。
比如我可以这样做:
let s = "";
for (let i=0; i < arr.length; i++) s += sep + arr[i];
// redundant separator at the beginning, need to remove it
s = s.substr(1);
或者像这样:
let s = "";
for (let i=0; i < arr.length; i++) s += arr[i] + sep;
// redundant separator at the end, need to remove it
s = s.slice(0, -1);
有没有更好的方法不产生多余的分隔符?导入该实现应该有效地处理所有情况,如空数组等。
我能想到的一种方法是在循环中放置一个 if
语句来检查它是否是 first/last 元素并且在这种情况下不添加分隔符,但这似乎效率低下。有什么想法吗?
如果您想自己定义它,您可以迭代到 length- 1
。循环后你可以只添加最后一项而不带分隔符。
例子
let arr = [1,2,3,4,5];
let sep = '-';
function customJoin(array, separator) {
if(array.length === 0) {
return '';
}
let s = '';
let length = array.length;
for (let i = 0; i < length - 1; i++) {
s += arr[i] + separator;
}
return s + arr[length - 1];
}
console.log(customJoin(arr, sep));
let s = arr[0] || "";
for (let i=1; i < arr.length; i++) s += sep + arr[i];
添加第一个元素,从第二个开始循环,在前面添加分隔符。
正如您在问题中指出的那样,您可以使用条件仅在需要时附加分隔符,从而无需删除多余的分隔符。问题是,如果您连接两个或三个值,它可能是正确的,但是必须在每个循环迭代中进行测试对于大数组来说成本会很高。
对于第一个元素,您可以检查数组的长度并获取字符串值或空字符串。
然后像 Salketer 在他的
let s = arr.length && arr[0].toString() || '';
for (let i=1; i < arr.length; i++) s += sep + arr[i];
另一种可能的选择是使用递归:
function join(a, separator) {
if (a.length === 0) return '';
function concat(a, n) {
return n > 0 ? concat(a, n - 1) + separator + a[n] : a[n];
}
return concat(a, a.length - 1);
}
一个限制是由于调用堆栈大小限制,它无法处理数万个字符的大字符串。
使用减少:
function join(arr, sep){
if (!arr.length)
return '';
return arr.reduce((a,b) => a + sep + b);
}
console.log(join([1,2],'^'));