Я хочу отсортировать массив объектов с определенным порядком, заданным из текста приоритета сортировки.
var sortPriority = "ramoklyxq";
items[
0:{data: "aizak", level: 'z'}
1:{data: "alice", level: 'r'}
2:{data: "bob", level: 'a'}
3:{data: "trinity", level: 'm'}
4:{data: "ella", level: 'z'}
5:{data: "John", level: 'z'}
6:{data: "bryan", level: 'z'}
7:{data: "sam", level: 'o'}
8:{data: "nick", level: 'k'}
9:{data: "angel", level: 'l'}
10:{data: "arla", level: 'z'}
11:{data: "marley", level: 'o'}
etc
]
i want to return as:
items[
0:{data: "alice", level: 'r'}
1:{data: "bob", level: 'a'}
2:{data: "trinity", level: 'm'}
3:{data: "marley", level: 'o'}
4:{data: "sam", level: 'o'}
5:{data: "nick", level: 'k'}
6:{data: "angel", level: 'l'}
7:{data: "aizak", level: 'z'}
8:{data: "arla", level: 'z'}
9:{data: "bryan", level: 'z'}
10:{data: "ella", level: 'z'}
11:{data: "John", level: 'z'}
etc
]
Есть ли способ отсортировать список по порядку data.level с уровня sortPriority. Если в sortPriority не существует уровня, он будет добавлен после, как в примере возврата.
Я использую эту функцию сначала для сортировки по уровню, а затем для данных.
for (let i = 0; i < items.length; i++) {
var list = document.getElementById('holder');
[...list.children]
.sort((a, b) => a.data.level > b.data.level ? 1 : -1)
.forEach(node => list.appendChild(node));
for (let j = 0; j < items.length; j++) {
var list = document.getElementById('holder');
[...list.children]
.sort((a, b) => a.data.data > b.data.data ? 1 : -1)
.forEach(node => list.appendChild(node));
}
}
Мне нужно что-то вроде этой функции с правильным приоритетом в ASC для результатов каждого уровня, чтобы я мог добавить ее в список, как показано.
Заранее спасибо.



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


Вы можете взять объект для заказа и отсортировать его соответствующим образом. Для того же приоритета сортируйте по строке.
const
sortPriority = "ramoklyxq",
data = [{ data: "aizak", level: 'z' }, { data: "alice", level: 'r' }, { data: "bob", level: 'a' }, { data: "trinity", level: 'm' }, { data: "ella", level: 'z' }, { data: "John", level: 'z' }, { data: "bryan", level: 'z' }, { data: "sam", level: 'o' }, { data: "nick", level: 'k' }, { data: "angel", level: 'l' }, { data: "arla", level: 'z' }, { data: "marley", level: 'o' }],
order = Object.fromEntries([...sortPriority].map((c, i) => [c, i + 1]));
order.default = Number.MAX_VALUE;
data.sort((a, b) =>
(order[a.level] || order.default) - (order[b.level] || order.default) ||
a.data.localeCompare(b.data)
);
console.info(data);.as-console-wrapper { max-height: 100% !important; top: 0; }@user2730288 user2730288 В вашем сообщении не говорилось, следует ли сохранять относительный порядок между элементами ввода с одинаковым приоритетом.
@Dai да, ты прав, я забыл упомянуть, что это должно быть в порядке ASC для каждого приоритета, я отредактирую как можно скорее. Спасибо!
Я использую его внутри цикла и, похоже, работает: ``` [...list.children].sort((a, b) => (order[a.data.level] || order.default) - (order[b.data.level] || order.default) || a.data.data.localeCompare(b.data.data)) .forEach(node => list.appendChild(node)); ```. Спасибо большое вам обоим!!!
const sortPriority = "ramoklyxq";
const items = [
{data: "aizak" , level: 'z'},
{data: "alice" , level: 'r'},
{data: "bob" , level: 'a'},
{data: "trinity", level: 'm'},
{data: "ella" , level: 'z'},
{data: "John" , level: 'z'},
{data: "bryan" , level: 'z'},
{data: "sam" , level: 'o'},
{data: "nick" , level: 'k'},
{data: "angel" , level: 'l'},
{data: "arla" , level: 'z'},
{data: "marley" , level: 'o'}
];
////
const priorityMap = Array.from( sortPriority ).reduce( ( m, ch, idx ) => { m.set( ch, idx + 1 ); return m; }, new Map() );
const output = items
.map( o => ({ o, order: priorityMap.get( o.level ) || Number.MAX_SAFE_INTEGER }) )
.sort( ( x, y ) => ( x.order - y.order ) || ( x.o.data.localeCompare( y.o.data ) ) )
.map( i => i.o )
;
console.info( output );Самый простой способ сделать это:
const items=[{data:'aizak',level:'z'},{data:'alice',level:'r'},{data:'bob',level:'a'},{data:'trinity',level:'m'},{data:'ella',level:'z'},{data:'John',level:'z'},{data:'bryan',level:'z'},{data:'sam',level:'o'},{data:'nick',level:'k'},{data:'angel',level:'l'},{data:'arla',level:'z'},{data:'marley',level:'o'}];
items.sort( sortItemsMethod('ramoklyxq') );
console.info( items );
// sort method :
function sortItemsMethod( priorytyLevels = '' )
{
const
pLlen = priorytyLevels.length + 1
, plOrder = s =>
{
let x = priorytyLevels.indexOf(s);
return (x < 0) ? ( pLlen + s.charCodeAt(0) ) : x;
};
return (a,b) => (plOrder(a.level) - plOrder(b.level)) || a.data.localeCompare(b.data);
}.as-console-wrapper{max-height:100% !important;top:0}
.as-console-row::after{display:none !important;}Есть ли способ отсортировать список по порядку data.level с уровня sortPriority. Если в sortPriority не существует уровня, он будет добавлен после, как в примере возврата.
Чтобы отсортировать item.level в том же порядке, что и sortPriority, нам нужно присвоить каждому символу значение, зависящее от порядка. Простое решение — использовать индекс, где "r" связан со значением 0, а "q" со значением 8. Их можно сохранить на Карте для быстрого поиска:
const sortPriority = "ramoklyxq";
const priorityMap = new Map(Array.from(sortPriority, (char, index) => [char, index]));
// representation of Map instance using object notation
// Map{
// "r": 0, "a": 1, "m": 2,
// "o": 3, "k": 4, "l": 5,
// "y": 6, "x": 7, "q": 8,
// }
Вышеупомянутое позволяет нам отсортировать массив на основе priorityMap с помощью:
items.sort((a, b) => priorityMap.get(a.level) - priorityMap.get(b.level));
Обратите внимание, что вышеизложенное работает, пока все level представлены в строке sortPriority. Поскольку это не так, нам нужно добавить значение по умолчанию. Поскольку вы хотите, чтобы все записи, отличные от sortPriority, располагались в конце, мы будем использовать число, большее, чем наибольший индекс. Например, это может быть size/length. Мы представим помощника для получения значения или значения по умолчанию.
const getPriority = (char) => priorityMap.get(char) ?? priorityMap.size;
Обратите внимание на использование ?? вместо ||. Причина использования ?? в том, что 0 считается ложным. Итак, если мы получим значение для первого символа, 0 || 9 приведет к 9, тогда как нам нужно 0. ?? возвращает правую часть только в том случае, если левая часть равна нулю (null или undefined), поэтому 0 будет возвращено. Если бы мы могли получить значение несуществующего символа, это было бы undefined ?? 9, которое возвращает 9. Это гарантирует, что не-записи будут помещены в конец, поскольку они имеют наибольшее значение.
Теперь мы можем сделать то же самое, что и раньше, но использовать помощник getPriority() вместо прямого вызова priorityMap.get().
items.sort((a, b) => getPriority(a.level) - getPriority(b.level));
Это должно соответствовать первоначальным критериям.
Я использую эту функцию сначала для сортировки по уровню, а затем для данных.
Для сортировки по data после этого вы можете просто использовать оператор ||. Возвращаемое значение 0 означает, что оба значения равны. Поскольку 0 ложно, оператор || вместо этого возвращает правую часть. Это означает, что элементы сначала будут упорядочены по уровню приоритета. Если уровни приоритета одинаковы, вместо этого мы упорядочиваем их по данным.
// SORT BY priority(level) ASC, data ASC
items.sort((a, b) => (
getPriority(a.level) - getPriority(b.level) || a.data.localeCompare(b.data)
));
Вышеупомянутое использует localeCompare() для сравнения по алфавиту. Вот пример фрагмента, объединяющего все вышеперечисленное в примере:
const sortPriority = "ramoklyxq";
const items = [
{ data: "aizak", level: 'z' },
{ data: "alice", level: 'r' },
{ data: "bob", level: 'a' },
{ data: "trinity", level: 'm' },
{ data: "ella", level: 'z' },
{ data: "John", level: 'z' },
{ data: "bryan", level: 'z' },
{ data: "sam", level: 'o' },
{ data: "nick", level: 'k' },
{ data: "angel", level: 'l' },
{ data: "arla", level: 'z' },
{ data: "marley", level: 'o' },
];
const priorityMap = new Map(Array.from(sortPriority, (char, index) => [char, index]));
const getPriority = (level) => priorityMap.get(level) ?? priorityMap.size;
items.sort((a, b) => (
getPriority(a.level) - getPriority(b.level) || a.data.localeCompare(b.data)
));
console.info(items);Поскольку ваш вопрос, по-видимому, касается сортировки DOM-узлов (в которые не включен HTML), вот пример того, как вы можете применить это в настройках манипуляции с DOM:
const sortPriority = "ramoklyxq";
const priorityMap = new Map(Array.from(sortPriority, (char, index) => [char, index]));
const getPriority = (char) => priorityMap.get(char) ?? priorityMap.size;
document.getElementById("sort-holder").addEventListener("click", function (event) {
const list = document.getElementById("holder");
const items = Array.from(list.children);
items.sort((a, b) => (
getPriority(a.dataset.level) - getPriority(b.dataset.level)
|| a.dataset.data.localeCompare(b.dataset.data)
));
list.replaceChildren(...items);
});
// non-relevant code, for demo purposes only
document.getElementById("shuffle-holder").addEventListener("click", function (event) {
const list = document.getElementById("holder");
const items = Array.from(list.children);
shuffle(items);
list.replaceChildren(...items);
});
function shuffle(arrayLike) {
for (let limit = arrayLike.length; limit > 1; --limit) {
const index = limit - 1;
const randomIndex = Math.trunc(Math.random() * limit); // random int 0 up to limit (exclusive)
if (index === randomIndex) continue; // skip if no swap is needed
[arrayLike[index], arrayLike[randomIndex]] = [arrayLike[randomIndex], arrayLike[index]];
}
}<ul id = "holder">
<li data-data = "aizak" data-level = "z">aizak (z)</li>
<li data-data = "alice" data-level = "r">alice (r)</li>
<li data-data = "bob" data-level = "a">bob (a)</li>
<li data-data = "trinity" data-level = "m">trinity (m)</li>
<li data-data = "ella" data-level = "z">ella (z)</li>
<li data-data = "John" data-level = "z">John (z)</li>
<li data-data = "bryan" data-level = "z">bryan (z)</li>
<li data-data = "sam" data-level = "o">sam (o)</li>
<li data-data = "nick" data-level = "k">nick (k)</li>
<li data-data = "angel" data-level = "l">angel (l)</li>
<li data-data = "arla" data-level = "z">arla (z)</li>
<li data-data = "marley" data-level = "o">marley (o)</li>
</ul>
<button id = "sort-holder">sort</button>
<button id = "shuffle-holder">shuffle</button>Судя по всему, будущее многословно. Не могу дождаться, пока ИИ научится редактировать так, чтобы звучать по-человечески.
@DaveNewton Вы имеете в виду, что я сгенерировал этот ответ с помощью ИИ? Если вам что-то не нравится в моей манере письма, вы можете отредактировать мой ответ, сделав его более человечным. Я не являюсь носителем английского языка, к тому же у меня дислектика, поэтому, возможно, поэтому ответ кажется вам немного неуместным. Если вы решите отредактировать ответ, используйте британский английский, пожалуйста.
как показано во фрагменте, ``` { "data": "bryan", "level": "z" }, { "data": "arla", "level": "z" }``` arla ниже Брайана с тем же уровнем