Есть массив объектов, которые мне нужно отсортировать. Выглядит это так:
var array = [
{left: 20, top: 50, group: 'groupOne'},
{left: 18, top: 10, group: 'groupTwo'},
{left: 15, top: 15, group: 'groupThree'},
{left: 25, top: 30, group: 'groupThree'},
{left: 18, top: 25, group: 'groupFour'},
{left: 28, top: 25, group: 'groupFive'},
{left: 25, top: 15, group: 'groupSix'},
{left: 30, top: 30, group: 'groupSix'}
];
Хочу отсортировать по левый (в первую очередь) и верхняя (во вторую). Моя функция сортировки выглядит так:
array.sort((x, y) => {
return x.left - y.left || x.top - y.top;
});
Результат:
[
{left: 15, top: 15, group: "groupThree"},
{left: 18, top: 10, group: "groupTwo"},
{left: 18, top: 25, group: "groupFour"},
{left: 20, top: 50, group: "groupOne"},
{left: 25, top: 15, group: "groupSix"},
{left: 25, top: 30, group: "groupThree"},
{left: 28, top: 25, group: "groupFive"},
{left: 30, top: 30, group: "groupSix"}
];
Функция сортировки работает почти так, как я хотел, но было бы лучше, если бы она также учитывала группа, если существует более одного элемента одной и той же группы.
Другими словами, я хочу, чтобы конечный результат выглядел так:
[
{left: 15, top: 15, group: "groupThree"},
{left: 25, top: 30, group: "groupThree"},
{left: 18, top: 10, group: "groupTwo"},
{left: 18, top: 25, group: "groupFour"},
{left: 20, top: 50, group: "groupOne"},
{left: 25, top: 15, group: "groupSix"},
{left: 30, top: 30, group: "groupSix"}
{left: 28, top: 25, group: "groupFive"},
];
Предметы из одной группы «склеиваются». Любые идеи?
А как две группы сортируются? На основе первого из группы?
Если у двух элементов одна и та же группа, их следует отсортировать так же, как и раньше (слева и вверху).
Поинти, что ты имеешь в виду?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы можете сгруппировать элементы и отсортировать сгруппированные элементы, а затем отсортировать по первому элементу сгруппированного элемента.
Позже сброшены все группы.
var array = [{ left: 20, top: 50, group: 'groupOne' }, { left: 18, top: 10, group: 'groupTwo' }, { left: 15, top: 15, group: 'groupThree' }, { left: 25, top: 30, group: 'groupThree' }, { left: 18, top: 25, group: 'groupFour' }, { left: 28, top: 25, group: 'groupFive' }, { left: 25, top: 15, group: 'groupSix' }, { left: 30, top: 30, group: 'groupSix' }],
leftTop = (a, b) => a.left - b.left || a.top - b.top,
sorted = Array
.from(
array
.reduce((m, o) => m.set(o.group, (m.get(o.group) || []).concat(o)), new Map)
.values(),
a => a.sort(leftTop)
)
.sort(([a], [b]) => leftTop(a, b))
.reduce((a, b) => a.concat(b));
console.info(sorted);.as-console-wrapper { max-height: 100% !important; top: 0; }Спасибо Нина, решение идеально подходит для меня. Но можете ли вы мне сказать еще кое-что? При отладке кода остановился на части .sort(([x], [y]) => leftTop(x, y)) (просто поменял буквы). Я знаю, что браузер иногда каким-то образом трансформирует код, чтобы читать его по-другому, но почему он изменил его на .sort(function(_a, _b) { var x = _a[0]; var y = _b[0]; return... }). Как браузер узнал, что нужно брать только первый элемент массива? Другими словами, как [x] изменился на _a[0]
это часть деструктуризация, где массив деструктурируется в массив и берется первый элемент. браузер знает это по синтаксису ES6.
Просто поместите
.localeCompare()для группы между сравнениями дляleftиtop. Другими словами, это то же самое, что вы уже делаете.