将字符串与分隔符连接起来的最有效方法是什么

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],'^'));