Группировать объекты массива по их значению - javascript

-4

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

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

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

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

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

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

Какой был бы лучший способ достичь этого?

Я пробовал обычный цикл loop, если условия, проверяющие разницу между следующим элементом с текущим, продолжаем нажимать его на массив, а когда разница больше 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);
}

спросил(а) 2021-01-25T23:20:36+03:00 5 месяцев назад
1
Решение
99

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

Изменение: после повторного чтения это не ясно, что массив ввода отсортирован или нет. Если он отсортирован, вы можете просто взглянуть на вызов сокращения.

Сначала мне было интересно, есть ли более оптимальное решение, чем O (nlogn). Тем не менее, даже если вы используете элементы bucketing, окончательный мега-массив по-прежнему полностью сортируется. Поэтому, если существует способ быстрее 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);

ответил(а) 2021-01-25T23:20:36+03:00 5 месяцев назад
45

Для этого вы можете использовать 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, и в комментариях выяснилось, что это предположение было правильным.

ответил(а) 2021-01-25T23:20:36+03:00 5 месяцев назад
45

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

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
}, [[]])

Обратите внимание, что он возвращает

[[]]

когда вызывается с пустым массивом, не должно быть?

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

ответил(а) 2021-01-25T23:20:36+03:00 5 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема