在JavaScript数组中所有元素之间穿插元素的方法是什么?

时间:2016-05-10 03:11:35

标签: javascript arrays ecmascript-6 lodash

假设我有一个数组var arr = [1, 2, 3],我希望用元素分隔每个元素,例如。 var sep = "&",因此输出为[1, "&", 2, "&", 3]

考虑它的另一种方法是我想做Array.prototype.join(arr.join(sep))而不是结果是一个字符串(因为我试图使用的元素和分隔符是对象,而不是字符串)。

是否有一种功能性/漂亮/优雅的方式在es6 / 7或lodash中执行此操作,而不会感觉像笨重的东西:

_.flatten(arr.map((el, i) => [el, i < arr.length-1 ? sep : null])) // too complex

_.flatten(arr.map(el => [el, sep]).slice(0,-1) // extra sep added, memory wasted

甚至

arr.reduce((prev,curr) => { prev.push(curr, sep); return prev; }, []).slice(0,-1)
// probably the best out of the three, but I have to do a map already
// and I still have the same problem as the previous two - either
// inline ternary or slice

编辑:Haskell具有此功能,称为intersperse

16 个答案:

答案 0 :(得分:17)

使用发电机:

function *intersperse(a, delim) {
  let first = true;
  for (const x of a) {
    if (!first) yield delim;
    first = false;
    yield x;
  }
}

console.log([...intersperse(array, '&')]);

感谢@Bergi指出输入可以是任何可迭代的有用概括。

如果你不喜欢使用发电机,那么

[].concat(...a.map(e => ['&', e])).slice(1)

答案 1 :(得分:7)

减少函数的传播和显式返回将使其更简洁:

const intersperse = (arr, sep) => arr.reduce((a,v)=>[...a,v,sep],[]).slice(0,-1)
// intersperse([1,2,3], 'z')
// [1, "z", 2, "z", 3]

答案 2 :(得分:4)

在ES6中,你要编写一个生成函数,它可以产生一个迭代器,它产生带有散布元素的输入:

function* intersperse(iterable, separator) {
    const iterator = iterable[Symbol.iterator]();
    const first = iterator.next();
    if (first.done) return;
    else yield first.value;
    for (const value of iterator) {
        yield separator;
        yield value;
    }
}

console.log(Array.from(intersperse([1, 2, 3], "&")));

答案 3 :(得分:3)

一种简单的方法可能就是为reduce函数提供一个初始数组,其大小比我们原始数组的两倍小,填充了用于散布的字符。然后将索引i处的原始数组的元素映射到最初馈送的目标数组中的2 * i将完美地完成工作。

在这种方法中,我没有看到(m)任何冗余操作。此外,由于我们在设置后没有修改任何数组大小,我不希望任何后台任务运行以进行内存重新分配,优化等。 另一个好处是使用标准数组方法,因为它们检查各种不匹配等等。

此函数返回一个新数组,其中被调用数组的项目散布在提供的参数中。

var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
Array.prototype.intersperse = function(s){
  return this.reduce((p,c,i) => (p[2*i]=c,p), new Array(2*this.length-1).fill(s));
}
document.write("<pre>" + JSON.stringify(arr.intersperse("&")) + "</pre>");

答案 4 :(得分:2)

javascript有一个方法join()和split()

var arr = ['a','b','c','d'];
arr = arr.join('&');
document.writeln(arr);

输出应为:a&amp; b&amp; c&amp; d

现在再次拆分:

arr = arr.split("");

arr现在:

arr = ['a','&','b','&','c','&','d'];

答案 5 :(得分:2)

使用reduce但没有slice

var arr = ['a','b','c','d'];
var lastIndex = arr.length-1;
arr.reduce((res,x,index)=>{
   res.push(x);
   if(lastIndex !== index)
    res.push('&');
  return res;
},[]);

答案 6 :(得分:1)

您可以使用Array.from创建最终大小的数组,然后使用callback参数实际填充它:

const intersperse = (arr, sep) => Array.from(
    { length: Math.max(0, arr.length * 2 - 1) }, 
    (_, i) => i % 2 ? sep : arr[i >> 1]
);
// Demo:
let res = intersperse([1, 2, 3], "&");
console.log(res);

答案 7 :(得分:0)

如果您的依赖项中有Ramda或者是否愿意添加它,则会有intersperse方法。

来自文档:

  

创建一个新的列表,并在元素之间插入分隔符。

     

调度第二个参数的intersperse方法(如果存在)。

R.intersperse('n', ['ba', 'a', 'a']); //=> ['ba', 'n', 'a', 'n', 'a']

或者您可以查看源代码库中的其中一种方法。 https://github.com/ramda/ramda/blob/v0.24.1/src/intersperse.js

答案 8 :(得分:0)

if (!Array.prototype.intersperse) {
  Object.defineProperty(Array.prototype, 'intersperse', {
    value: function(something) {
      if (this === null) {
        throw new TypeError( 'Array.prototype.intersperse ' + 
          'called on null or undefined' );
      }
      var isFunc = (typeof something == 'function')

      return this.concat.apply([], 
        this.map(function(e,i) { 
          return i ? [isFunc ? something(this[i-1]) : something, e] : [e] }.bind(this)))
    }
  });
}

答案 9 :(得分:0)

您还可以使用以下内容:

var arr =['a', 'b', 'c', 'd'];
arr.forEach(function(element, index, array){
    array.splice(2*index+1, 0, '&');
});
arr.pop();

答案 10 :(得分:0)

我的看法:

const _ = require('lodash');

_.mixin({
    intersperse(array, sep) {
        return _(array)
            .flatMap(x => [x, sep])
            .take(2 * array.length - 1)
            .value();
    },
});

// _.intersperse(["a", "b", "c"], "-")
// > ["a", "-", "b", "-", "c"]

答案 11 :(得分:0)

const arr = [1, 2, 3];

function intersperse(items, separator) {
  const result = items.reduce(
    (res, el) => [...res, el, separator], []);
  result.pop();
  return result;
}

console.log(intersperse(arr, '&'));

答案 12 :(得分:0)

几年后,这是一个递归生成器解决方案。享受吧!

const intersperse = function *([first, ...rest], delim){
    yield first;
    if(!rest.length){
      return;
    }
    yield delim;
    yield * intersperse(rest, delim);
};
console.log([...intersperse(array, '&')]);

答案 13 :(得分:0)

export const intersperse = (array, insertSeparator) => {
  if (!isArray(array)) {
    throw new Error(`Wrong argument in intersperse function, expected array, got ${typeof array}`);
  }

  if (!isFunction(insertSeparator)) {
    throw new Error(`Wrong argument in intersperse function, expected function, got ${typeof insertSeparator}`);
  }

  return flatMap(
    array,
    (item, index) => index > 0 ? [insertSeparator(item, index), item] : [item] // eslint-disable-line no-confusing-arrow
  );
};

答案 14 :(得分:0)

单线和快速

const intersperse = (ar,s)=>[...Array(2*ar.length-1)].map((_,i)=>i%2?s:ar[i/2]);

console.log(intersperse([1, 2, 3], '&'));

答案 15 :(得分:-2)

更新了不使用连接方法的对象:

for (var i=0;i<arr.length;i++;) {
    newarr.push(arr[i]);
    if(i>0) { 
      newarr.push('&'); 
     }    
}

newarr应该是:

newarr = ['a','&','b','&','c','&','d'];