Подтвердить что ты не робот

Тесный способ пересечения элемента между всеми элементами массива JavaScript?

Скажем, у меня есть массив 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

4b9b3361

Ответ 1

Использование генератора:

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)

Ответ 2

Распространение и явное возвращение в сокращающую функцию сделает его более кратким:

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

Ответ 3

В 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], "&")));

Ответ 4

Один простой подход может быть похож на подачу функции уменьшения с начальным массивом размером один меньше, чем двойной из нашего исходного массива, заполненный символом, который будет использоваться для перемешивания. Тогда отображение элементов исходного массива с индексом я в 2 * я в исходном массиве целевых массивов выполнило бы работу отлично.

В этом подходе я не вижу (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>");

Ответ 5

javascript имеет метод join() и split()

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

Выход должен быть: a & c & d

теперь снова разделяется:

arr = arr.split("");

arr теперь:

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

Ответ 6

Использование 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;
},[]);

Ответ 7

Если у вас Ramda в ваших зависимостях или если вы хотите добавить его, то 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

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

вы также можете использовать следующее:

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

Ответ 10

Мой дубль:

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

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

Обновлен для объектов, не использующих метод соединения:

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

newarr должен быть:

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