Разбить массив на куски произвольной длины между заданным диапазоном - PullRequest
0 голосов
/ 27 февраля 2019

Мне нужна помощь, пожалуйста.
Итак, у меня есть следующий массив:

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

Я пытаюсь разбить этот массив на куски с длинами между заданным диапазоном

const minChunkSize = 2;
const maxChunkSize = 5;

Таким образом, размер порции может быть любым между minChunksize и maxChunkSize, сгенерированными случайным образом.

Возможные выходы:

[[1, 2, 3], [4, 5, 6, 7], [8, 9, 10]]
or
[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]
or
[[1, 2], [3, 4, 5, 6, 7], [8, 9, 10]]
or
[[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]

etc...

Спасибо за вашу помощь!

Ответы [ 3 ]

0 голосов
/ 27 февраля 2019

Это немного неэффективно, но вы можете создать рекурсивный метод, который постепенно slice () случайное число (между некоторыми min и max) элементов измассив.Если конечный сгенерированный результат имеет массив some () , длина которого меньше минимальной, метод вызывает сам себя.

const randSplit = (arr, min, max) =>
{
    // Check arguments.

    if (min > arr.length || max <= min)
        return [arr];

    let res = [], i = 0, rnd;

    while (i < arr.length)
    {        
        rnd = Math.floor(Math.random() * (max - min)) + min;
        res.push(arr.slice(i, i + rnd));
        i += rnd;
    }

    if (res.some(x => x.length < min))
        return randSplit(arr, min, max)
    else
        return res;
}

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
console.log(JSON.stringify(randSplit(arr, 2, 5)));
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
0 голосов
/ 27 февраля 2019

Даже если это не самое эффективное решение, вы можете попытаться сгенерировать чанки, и если последний элемент короче минимального требуемого значения, вы попытаетесь сгенерировать его снова (рекурсия), например так:

const generate = (input, min, max) => {
  const random = (min, max) => Math.floor(Math.random() * (max - min + 1)) + min;
  
  const inner = arr => {
    if (arr.length === 0) return;
    
    const minIndex = arr.length < min ? arr.length : min;;
    const maxIndex = arr.length < max ? arr.length : max;
    
    const splitIndex = random(minIndex, maxIndex);
    
    const generatedArray = arr.slice(0, splitIndex);
    const remainingArray = arr.slice(splitIndex);
    
    if (remainingArray.length === 0) {
      return [generatedArray];
    } else {
      return [generatedArray].concat(inner(remainingArray));
    }
  };
  
  const result = inner(input);
  return result.every(item => item.length >= min) ? result : generate(input, min, max);
};

console.log(
  generate(
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
    2,
    4,
  )
);
0 голосов
/ 27 февраля 2019

Рекурсивная функция сделает работу:

var N = 150;
var test = Array.apply(null, {length: N}).map(Number.call, Number);

console.log('inputArray', test);

var minChunkSize = 2;
var maxChunkSize = 5;

function chunk(inputArray, minChunkSize, maxChunkSize) {
  if(inputArray.length <= maxChunkSize) {
    return inputArray;
  }

  return inputArray.splice(0, Math.round(Math.random() * (maxChunkSize - minChunkSize)) + minChunkSize);
}

function chunkAll(inputArray, minChunkSize, maxChunkSize) {
  var ret = [];
  while(inputArray.length > maxChunkSize) {
    ret.push(chunk(inputArray, minChunkSize, maxChunkSize));
  }
  if(inputArray.length > 0) {
    ret.push(inputArray);
  }
  return ret;
}

console.log('chunked', chunkAll(test, minChunkSize, maxChunkSize));
...