在数组元素之间插入对象的最优雅的方式是什么?

What is the most elegant way to insert objects between array elements?

本文关键字:方式 是什么 之间 插入 对象 数组元素      更新时间:2023-09-26

我相信有很多方法可以做到这一点,但我正在寻找一些"优雅"的东西。

a = [
  'a',
  'b',
  'c'
];
magicArrayJoin(a, {value: 255} ); // insert the same object between each item
result ==  [
  'a',
  {value: 255},
  'b',
  {value: 255}
  'c'
];

欢迎所有建议。:)

使用普通ES6的一行代码:

const interleave = (arr, thing) => [].concat(...arr.map(n => [n, thing])).slice(0, -1)

用法:

interleave(['foo', 'bar', 'baz'], 'avocado')

打印:

> ["foo", "avocado", "bar", "avocado", "baz"]

可以使用flatMap。它可以从lodash中找到,例如

_.flatMap([1,2,3,4], (value, index, array) =>
     array.length -1 !== index // check for the last item
     ? [value, "s"]
     : value
);

输出

[1, "s", 2, "s", 3, "s", 4]

更新

array# flatMap的建议是在工作中,所以在未来这应该工作:

[1, 2, 3, 4].flatMap(
    (value, index, array) =>
        array.length - 1 !== index // check for the last item
            ? [value, "s"]
            : value,
);

我认为最优雅的方法是:

ES6语法版本

const insertIntoArray = (arr, value) => {
    return arr.reduce((result, element, index, array) => {
        result.push(element);
        if (index < array.length - 1) {
            result.push(value);
        }
        return result;
    }, []);
};

用法:

insertIntoArray([1, 2, 3], 'x'); // => [1, 'x', 2, 'x', 3]

使用ES6 flatMap函数

const insertBetween = (ele, array) => {
  return array.flatMap((x) => [ele, x]).slice(1);
};
insertBetween('+', [1, 2, 3]);

普通循环似乎是最好的:

function intersperse(arr, el) {
    var res = [], i=0;
    if (i < arr.length)
        res.push(arr[i++]);
    while (i < arr.length)
        res.push(el, arr[i++]);
    return res;
}

如果你在寻找一些优雅的东西,它可能不得不使用某种concatMap,如

function concatMap(arr, fn) { return [].concat.apply([], arr.map(fn)); }
function intersperse(arr, el) { return concatMap(arr, x => [el, x]).slice(1); }

不可变解决方案

当减少一个数组时,reduce函数不应该改变数组,而是返回一个新值(在本例中是一个新数组)。这样,更改将只应用于返回的数组而不是原始数组,并且可以避免副作用。

const insertBetween = (insertee, array) => array.reduce(
    (acc, item, i, { length }) => {
        if (i && i < length) {
            return [...acc, insertee, item];
        }
        return [...acc, item];
    },
    []
);

Ramda有一个intersperse方法

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

代码:

R.intersperse({name: 'separator'}, ['one', 'two', 'three']);
结果:

[
    'one',
    {name: 'separator'},
    'two',
    {name: 'separator'},
    'three'
]

您可以使用reduce(它也是不可变的)来实现这一点。

const insertBetween = (insertion, array) =>
    array.reduce(
        (newArray, member, i, array) =>
            i < array.length - 1 
                ? newArray.concat(member, insertion) 
                : newArray.concat(member),
        []
    );
const result = insertBetween('and', [1, 2, 3]);
console.log(result);
// outputs;
// [
//   1, 
//   'and', 
//   2, 
//   'and', 
//   3
// ]

或者在旧的JS语法中;

function insertBetween(insertion, array) {
    const indexOfLastItem = array.length - 1;
    return array.reduce(withInsertion, []);
    function withInsertion(newArray, item, index, array) {
        return index < indexOfLastItem 
            ? newArray.concat(item, insertion) 
            : newArray.concat(item);
    }
}
const result = insertBetween('and', [1, 2, 3]);
console.log(result);
// outputs;
// [
//   1, 
//   'and', 
//   2, 
//   'and', 
//   3
// ]

我真的很喜欢@Vidul的评论,它非常有逻辑性和简洁!我自己也提出了splice(),但错过了%。然而,对于在线用户来说,大多数大括号似乎都是不必要的。可以进一步简化为

for (var i = 0; i < a.length; i++) if (i % 2) a.splice(i, 0, {value: 255});
const arr = ['apple', 'banana', 'orange'];
arr.flatMap(item => [item, ', ']).slice(0, -1);
// ["apple", ", ", "banana", ", ", "orange"]

这对我有用:

 a.map(val => [val, {value: 255}]).flat()
function insertObject(arr, obj) {
  var result = [];
  function insert(element, index) {
    result.push(element);
    if (index + 1 < arr.length) {
      result.push(obj);
    }
  }
  arr.forEach(insert);
  return result;
}
var a = [1, 2, 3, 4];
insertObject(a, {
  test: 'test'
});

使用Kamen建议的splice,您可以这样做:

const numSeparators = arr.length - 1;
for (let i = 1; i <= numSeparators; i++) {
    const index = (i * 2) - 1;
    arr.splice(index, 0, { value: 255 });
}

对于一个简单的纯函数方式,我建议这样做:

const magicArrayJoin = (array, el) =>
  array.length ?
    array.slice(1).reduce((acc, cur) => acc.concat([el, cur]), [array[0]]) :
    []

期票这种方式在javascript中不是最高效的

ES6:

const arrayWithSeparator = array.reduce((a, i) => a.length ? a.push(separator) && a.push(i) && a : a.push(u) && a, [])