Задать вопрос
dataarray
@dataarray

Как получить массив массивов с 2-мя объектами из 2-ух массивов с объектами?

Вопрос: Как получить массив (см. ниже arrThree) с n-ым количеством массивов, где в каждом таком массиве находятся два объекта ~ из двух массивов с объектами (arrOne и arrTwo)?

1. В массивах arrOne и arrTwo всегда одинаковое количество объектов
2. Количество объектов в массивах arrOne и arrTwo всегда – чётное (2, 4, 6, 8, ... )
3. Массив объектов формируется по принципу 1-ый объект из 1-го массива arrOne и 1-ый объект из 2-го массива arrTwo, 2-ой объект из 1-го массива arrOne и 2-ой объект из 2-го массива arrTwo . . . и т.д.

Массив arrOne
[
  {
    path: './name-1.jpg',
    filename: 'name-1'
  },
  {
    path: './name-3.jpg',
    filename: 'name-3'
  },
  {
    path: './name-5.jpg',
    filename: 'name-5'
  }
]


Массив arrTwo
[
  {
    path: './name-2.jpg',
    filename: 'name-2'
  },
  {
    path: './name-4.jpg',
    filename: 'name-4'
  },
  {
    path: './name-6.jpg',
    filename: 'name-6'
  }
]


Массив arrThree – нужно получить
[
 [
  {
    path: './name-1.jpg',
    filename: 'name-1'
  },
  {
    path: './name-2.jpg',
    filename: 'name-2'
  }
 ],
 [
  {
    path: './name-3.jpg',
    filename: 'name-3'
  },
  {
    path: './name-4.jpg',
    filename: 'name-4'
  }
 ],
 [
  {
    path: './name-5.jpg',
    filename: 'name-5'
  },
  {
    path: './name-6.jpg',
    filename: 'name-6'
  }
 ]
]
  • Вопрос задан
  • 128 просмотров
Подписаться 1 Средний Комментировать
Решения вопроса 1
0xD34F
@0xD34F Куратор тега JavaScript
Не будем ограничиваться двумя массивами, решим задачу в более общем виде - пусть источников данных будет произвольное количество. Возможны разные варианты:

  1. Если уверены, что длины всех массивов будут равны:

    const zip = (...arrs) =>
      arrs[0]?.map((n, i) => arrs.map(m => m[i])) ?? [];
    
    
    const result = zip(arr1, arr2);


  2. Вместо отсутствующих значений подставляем какое-то дефолтное:

    const zip = (arrs, defaultValue = null) =>
      Array.from(
        { length: Math.max(...arrs.map(n => n.length)) },
        (n, i) => arrs.map(m => i < m.length ? m[i] : defaultValue)
      );
    
    // или
    
    const zip = (arrs, defaultValue = null) =>
      arrs.reduce((acc, n, i) => (
        n.forEach((m, j) => (acc[j] ??= Array(arrs.length).fill(defaultValue))[i] = m),
        acc
      ), []);

    В вашем случае применять, понятное дело, так: const result = zip([ arr1, arr2 ]);.

    Пример с разными длинами массивов - zip([ [ 1, 2, 3 ], [], [ 99 ] ], Infinity) - в результате получим

    [
      [ 1, Infinity,       99 ],
      [ 2, Infinity, Infinity ],
      [ 3, Infinity, Infinity ]
    ]


  3. В качестве источников данных могут выступать не обязательно массивы:

    function* zip(data, defaultValue = null) {
      const iterators = Array.from(data, n => n[Symbol.iterator]());
    
      for (let doneAll = false; (doneAll = !doneAll);) {
        const values = [];
    
        for (const n of iterators) {
          const { value, done } = n.next();
          values.push(done ? defaultValue : value);
          doneAll &&= done;
        }
    
        if (!doneAll) {
          yield values;
        }
      }
    }

    В вашем случае применять так: const result = [...zip([ arr1, arr2 ])];.

    Пример посложнее, результатом выражения

    Array.from(zip((function*() {
      yield [ , true, false, NaN ];
      yield 'abcde';
      yield Array(3).keys();
    })()))

    будет следующий массив:

    [
      [ undefined, 'a',    0 ],
      [      true, 'b',    1 ],
      [     false, 'c',    2 ],
      [       NaN, 'd', null ],
      [      null, 'e', null ]
    ]


Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы