Группировать объекты массива по их значению - javascript - PullRequest
0 голосов
/ 17 мая 2018

Я пытаюсь найти лучший способ сгруппировать массив в несколько массивов, основываясь на какой-то операции со значениями массива ...

Например, мой массив выглядит как

var arr = [100, 200, 300, 500, 600, 700, 1000, 1100, 1200]

Мне нужносгруппировать вышеуказанный массив в разные массивы, как только разница превысит 100.

Итак, мой вывод будет выглядеть так:

var result = [[100, 200, 300], [500, 600, 700], [1000, 1100, 1200]]

Каков наилучший способ для достижения этой цели?

Я попробовал обычный цикл for, если условия проверяют разницу между следующим элементом и текущим, продолжайте помещать его в массив, а когда разница больше 100, создайте новый массив.

Я чувствую, что должен быть лучший способ сделать это.

РЕДАКТИРОВАТЬ: -

Я пробовал приведенный ниже код, он близок, но не завершен.Не тратил больше времени на это, так как я пытался получить более простую версию, используя сокращение или подчеркивание -

var result = [], temp = [], difference;
for (var i = 0; i < array.length; i += 1) {
 if (difference !== (array[i + 1] - array[i])) {
    if (difference !== undefined) {
        result.push(temp);
        temp = [];
    }
    difference = array[i + 1] - array[i];
}
temp.push(array[i]);
}

if (temp.length) {
  result.push(temp);
}

Ответы [ 3 ]

0 голосов
/ 17 мая 2018

Это интересный вопрос.

Редактировать: после перечитывания не понятно, отсортирован ли входной массив или нет. Если он отсортирован, вы можете просто посмотреть на сокращение вызова.

Сначала мне было интересно, есть ли более оптимальное решение, чем O (nlogn). Тем не менее, даже если вы группируете элементы, окончательный мега-массив все еще полностью отсортирован. Поэтому, если существует способ быстрее O (nlogn) решить вашу проблему, вы также можете решить сортировку быстрее, чем nlogn.

Учитывая это, наиболее простым решением является сортировка массива, а затем разделение его в соответствии с последним элементом при выполнении итерации по нему. Reduce в итоге становится идеальным инструментом:

const input = [100, 200, 300, 500, 600, 700, 1000, 1100, 1200];

const sorted = input.slice().sort((a, b) => a - b);

const buckets = sorted.reduce((buckets, item, i) => {
  const lastBucket = buckets[buckets.length - 1];
  if (i === 0) {
    return [[item]];
  }
  const prev = sorted[i - 1];
  if (item - prev > 100) {
    buckets.push([item]);
  } else {
    buckets[buckets.length - 1].push(item);
  }
  return buckets;
}, [])
console.log(buckets);
0 голосов
/ 31 мая 2018

Поскольку не было никакого ответа с использованием полных аргументов замещения, в одной функции:

var arrOrg = [100, 200, 300, 500, 600, 700, 1000, 1100, 1200]
arrOrg.reduce(function (acc, item, idx, arr) {
  if (idx) {
    (idx < arr.length && arr[idx + 1] > item + 100) // the spec condition
      ? acc[acc.length] = [item]
      : acc[acc.length - 1].push(item)
  } else acc[0][0] = item
  return acc
}, [[]])

Обратите внимание, что при вызове с пустым массивом возвращается

[[]]

, не должен

Также обратите внимание, что сортировка не имеет значения.

0 голосов
/ 17 мая 2018

Для этого можно использовать reduce.

var arr = [100, 200, 300, 500, 600, 700, 1000, 1100, 1200];

var groups = arr.reduce(function (a, b) {
  if (a.length === 0) { // First Iteration
    a.push([b]);
    return a;
  }

  var lastGroupIndex = a.length - 1;
  var lastGroup = a[lastGroupIndex];

  var lastElementIndex = lastGroup.length - 1;
  var lastElement = lastGroup[lastElementIndex];

  if (b - lastElement <= 100) { // Add to current group
    lastGroup.push(b);
    return a;
  }

  a.push([b]); // Create new group
  return a;
}, [])

Примечание. Это решение не использует функции ES6.Из первоначального вопроса я сделал предположение об использовании var, что кодовая база не была на ES6, и в комментариях выяснилось, что это предположение было правильным.

...