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

Как разбить массив на части заданного размера?

1. У меня есть условный массив с объектами
2. Объектов в этом массиве может быть много
3. Количество объектов всегда – чётное (2, 4, 6, 8 , ...)

[
  {
    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'
  }
]

Это массив фотографий из папок файловой системы. Мне нужно отправлять по 2 фотографии на почту одним сообщением. В данном случае (выше) у меня 4 фотографии, то есть, мне нужно отправить 2 письма.
Для того, чтобы nodeMailer сработал корректно, ему нужно передать массив объектов.

Вопрос: как получить n-ое количество массивов с двумя объектами из массива с n-ым количеством объектов?
  • Вопрос задан
  • 255 просмотров
Подписаться 1 Простой 2 комментария
Решения вопроса 2
0xD34F
@0xD34F Куратор тега JavaScript
Можно рассматривать нарезание массива на куски как самостоятельную операцию:

const chunked = (arr, chunkSize) =>
  arr.reduce((acc, n, i) => (
    (i % chunkSize) || acc.push([]),
    acc.at(-1).push(n),
    acc
  ), []);


console.log(chunked([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], 3));

А можно - как частный случай группировки, и не обязательно одних только массивов:

const group = (data, key) =>
  Array.prototype.reduce.call(
    data,
    (acc, n, i, a) => ((acc[key(n, i, a)] ??= []).push(n), acc),
    {}
  );

const chunked = (data, chunkSize) =>
  Object.values(group(data, (_, i) => i / chunkSize | 0));


console.log(chunked('0123456789', 3));
console.log(chunked(document.querySelectorAll('img'), 5));

Если режем на куски не массив, то и кусками тоже могут быть не массивы, а значения исходного типа (если данный тип поддерживает операцию получения куска значения):

const chunked = (data, chunkSize, slice = data.slice) =>
  Array.from(
    { length: Math.ceil(data.length / chunkSize) },
    function(_, i) {
      return this(i * chunkSize, (i + 1) * chunkSize);
    },
    (slice instanceof Function ? slice : Array.prototype.slice).bind(data)
  );


console.log(chunked('abcdefghij', 4)); // так кусками будут тоже строки
console.log(chunked('abcdefghij', 4, [].slice)); // а так - массивы
console.log(chunked($('img'), 5));

В качестве исходных данных могут выступать не только массивоподобные объекты, но и итерируемые, а саму выдачу кусков можно оформить в виде генератора:

function* chunked(data, chunkSize) {
  let chunk = [];

  for (const n of data) {
    if (chunk.push(n) === chunkSize) {
      yield chunk;
      chunk = [];
    }
  }

  if (chunk.length) {
    yield chunk;
  }
}


console.log(Array.from(chunked([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ], 3)));
console.log([...chunked(document.querySelectorAll('img'), 5)]);
for (const n of chunked(Array(10).keys(), 4)) {
  console.log(n);
}
Ответ написан
Комментировать
MrDecoy
@MrDecoy Куратор тега JavaScript
Верставший фронтендер
Или в более понятном виде:
[
  {
    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'
  }
].reduce((acc, item, idx, arr) => { if (idx % 2) { acc.push([ arr[idx-1], item ]) } return acc }, [])

/*
[
  [
    { 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' }
  ]
]
*/
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

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

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