Расположить похожие объекты в массиве рядом
Я работаю с большими данными, вот упрощённый пример
[
{ a: '0', b: '1' },
{ a: '0', b: '0' },
{ a: '1', b: '1' },
{ a: '2', b: '0' },
{ a: '0', b: '0' },
{ a: '0', b: '1' },
]
Мне нужно расположить похожие по некоторым свойствам записи рядом, например так (порядок не имеет значения)
[
{ a: '0', b: '1' },
{ a: '0', b: '1' },
{ a: '0', b: '0' },
{ a: '0', b: '0' },
{ a: '1', b: '1' },
{ a: '2', b: '0' },
]
С небольшими данным справляется Array.prototype.sort:
data.sort(({ a: a1, b: b1 }, { a: a2, b: b2 }) => a1 === a2 && b1 === b2 ? 0 : 1)
Но вот с большими данными (100к+) это вообще не даёт результата (т.е. записи которые должны быть рядом находятся в разным местах массив)
Оригинальная функция сравнения:
function compare<T>(a: T, b: T, compareKeys: (keyof T)[], dateField: keyof T) {
const dateFiledA = a[dateField] as unknown as Date
const dateFiledB = b[dateField] as unknown as Date
return compareKeys
.map((c) => a[c] === b[c])
.concat([
dateFiledA.getFullYear() === dateFiledB.getFullYear() &&
dateFiledA.getMonth() === dateFiledB.getMonth() &&
dateFiledA.getDate() === dateFiledB.getDate(),
])
.every(Boolean) ? 0 : 1
}
Ответы (1 шт):
Автор решения: SwaD
→ Ссылка
Скорее всего вам надо правильно прописать фукнцию сравнения. Вот пример для 150к элементов
// Создаем массив в 150к элементов
console.time('add')
const y = [];
for (let i = 0; i <=150000; i++) {
y.push({
a: Math.round(Math.random() * 100).toString(),
b: Math.round(Math.random() * 100).toString()
})
}
console.timeEnd('add');
// Сортируем
console.time('go');
function microSort(c,d) {
if (c > d) return 1;
if (c < d) return -1;
return 0
}
y.sort((q,w) => {
if (q.a === w.a) {
return microSort(q.b, w.b);
}
return microSort(q.a, w.a)
})
console.timeEnd('go')
console.log(y.slice(0, 10)); // Первые 10 записей
console.log(y.slice(-10)); // Последние 10 записей
Так же при сравнении надо учитывать тип данных при сравнении. Если есть вложенные объекты, их сортировку придется прописывать отдельно