Разбить массив на куски разных размеров (4, 3, 3, 3, 4, 3, 3, 3 и т. Д. c) - PullRequest
4 голосов
/ 14 февраля 2020

У меня есть такой массив: [1, 2, 3, 4, 5, 6, 7, 9, 10]. Мне нужно разбить его на куски разных размеров, но с простым шаблоном: 4, 3, 3, 3, 4, 3, 3, 3, например так:

[
    [ // four
        1,
        2,
        3,
        4
    ],
    [ // three (1/3)
        5,
        6,
        7
    ],
    [ // three (2/3)
        8,
        9,
        10
    ],
    [ // three (3/3)
        11,
        12,
        13
    ],
    [ // four
        14,
        15,
        16,
        17
    ],
    [ // three (1/3)
        18,
        19,
        20
    ], // and so on..
]

Я пробовал с этим кодом Я настроил:

const arr; // my array of values
const chuncked = arr.reduce((acc, product, i) => {
    if (i % 3) {
        return acc;
    } else if (!didFourWayReduce) {
        didFourWayReduce = true;
        fourWayReduces++;

        if ((fourWayReduces - 1) % 2) { // only make every second a "4 row"
            return [...acc, arr.slice(i, i + 3)];
        } else {
            return [...acc, arr.slice(i, i + 4)];
        }
    } else {
        didFourWayReduce = false;
        return [...acc, arr.slice(i, i + 3)];
    }
}, []);

И это работает, почти ожидая, что первый кусок тройки (1/3) имеет последний элемент фрагмента с 4. Таким образом, 1 ключ повторяется каждый первый фрагмент три. Вот так:

[
    [
        1,
        2,
        3,
        4
    ],
    [
        4, // this one is repeated, and it shouldn't be
        5,
        6
    ]
]

Ответы [ 5 ]

6 голосов
/ 14 февраля 2020

Вы можете взять два индекса, один для массива данных и один для размеров. Затем нарежьте массив заданной длины и добавьте pu sh chunk к массиву chunks.

Продолжайте до конца данных.

var data = Array.from({ length: 26 }, (_, i) => i + 1),
    sizes = [4, 3, 3, 3],
    i = 0,
    j = 0,
    chunks = [];

while (i < data.length) chunks.push(data.slice(i, i += sizes[j++ % sizes.length]));

console.log(chunks);
.as-console-wrapper { max-height: 100% !important; top: 0; }
1 голос
/ 14 февраля 2020

Рекурсивный подход довольно элегантен:

const chunks = (xs, [s, ...ss]) =>
  xs.length ? [xs .slice (0, s), ... chunks (xs .slice (s), [...ss, s])] : []

const data = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
const sizes = [4, 3, 3, 3]

console .log (chunks (data, sizes))
.as-console-wrapper { max-height: 100% !important; top: 0; }

Заменив [s, ...ss] на [...ss, s], мы передаем циклическую версию массива размеров, так что, например, [4, 3, 3, 3] становится [3, 3, 3, 4] , Это облегчает пошаговый анализ.

1 голос
/ 14 февраля 2020

const arr = Array.from({ length: 100 }, (_, i) => i);

const copy = [...arr];

const sizes = [4, 3, 3, 3];

const result = [];

let i = 0;

while (i <= arr.length && copy.length) {
  result.push(copy.splice(0, sizes[i % sizes.length]));
  i++;
}

console.log(result);
0 голосов
/ 14 февраля 2020

Этот ответ аналогичен ответу Нины Шольц , но использует для l oop, что лично мне кажется более понятным.

const arr = Array.from({length: 100}, (_, i) => i + 1);
const sizes = [4, 3, 3, 3];
const result = [];

for (let i = 0, j = 0; i < arr.length; i += sizes[j], j = (j + 1) % sizes.length) {
  result.push(arr.slice(i, i + sizes[j]));
}

console.log(result);
0 голосов
/ 14 февраля 2020

Мод оператора, чтобы проверить, должно ли оно быть 4 или 3. Используйте два массива только для упрощения (можно сделать с одним)

const groupIt = arr => arr.reduce(({
  group,
  out
}, v, i) => {
  var max = out.length % 4 === 0 ? 4 : 3
  group.push(v)
  if (group.length === max || i === arr.length - 1) {
    out.push(group)
    group = []
  }
  return {
    group,
    out
  }
}, {
  group: [],
  out: []
}).out

console.log(groupIt([1, 2, 3, 4, 5, 6, 7, 8]))

var test = (new Array(30)).fill(0).map((x,i) => i + 1)
console.log(groupIt(test))

только с одним:

const groupIt = arr => arr.reduce((out, v, i) => {
  var max = (out.length - 1) % 4 === 0 ? 4 : 3
  out[out.length - 1].push(v)
  if (out[out.length - 1].length === max) {
    out.push([])
  }
  return out
}, [[]])

console.log(groupIt([1, 2, 3, 4, 5, 6, 7, 8]))

var test = (new Array(30)).fill(0).map((x, i) => i + 1)
console.log(groupIt(test))
...