У меня есть массив или объект, который будет служить столбцом для таблицы с уникальным ключом.
const list = [{
key: "Name",
textColor: "red"
},{
key: "Age",
textColor: "green"
},{
key: "Occupation",
textColor: "yellow"
}]
И у меня есть список упорядочения столбцов в таблице
const newOrder = ["Occupation", "Name", "Age"]
Теперь, как я могу изменить список в соответствии с newOrder без использования nested loops
. Кроме того, все они являются динамическими, поэтому речь идет не только о вышеупомянутых трех столбцах.
Ожидаемый результат
const list = [{
key: "Occupation",
textColor: "yellow"
},{
key: "Name",
textColor: "red"
},{
key: "Age",
textColor: "green"
}]
На данный момент порядок сортировки в обратном алфавитном порядке. О, Н, А. Так будет всегда?
Вы можете использовать Сортировать по из библиотеки lodash
Ваш список можно переформатировать в обычный объект javascript, в котором key
— это имя свойства, а textColor
— это значение:
const toObject = kvps => Object.fromEntries(kvps.map(kvp => [ kvp.key, kvp.textColor ]));
С заданным массивом ключей вы можете выбирать значения из этого объекта следующим образом:
const fromObject = (order, obj) => order.map(key => ({ key, textColor: obj[key] }));
Соедините их вместе, и вы можете изменить порядок любого списка пар ключ-значение:
const list = [{
key: "Name",
textColor: "red"
},{
key: "Age",
textColor: "green"
},{
key: "Occupation",
textColor: "yellow"
}]
const toObject = kvps => Object.fromEntries(kvps.map(kvp => [ kvp.key, kvp.textColor ]));
const fromObject = (order, obj) => order.map(key => ({ key, textColor: obj[key] }));
const reorder = (order, kvps) => fromObject(order, toObject(kvps));
const newList = reorder(["Occupation", "Name", "Age"], list);
console.info(
newList
)
Edit: if the sizes of your list and order arrays are small, you probably want to go with the much easier to read approach suggested by Jon Webb in one of the other answers. ? I tried to keep my solution to an O(n + m) complexity rather than O(n * m), (n = list size, m = order size) but it's probably not worth the added complexity.
Это менее сложное решение, которое я искал.
Вы можете выполнить итерацию по списку "заказ", найдя соответствующий элемент в исходном списке, и поместить элемент в новый список в указанном порядке:
const orderList = (list, order) => {
const newList = [];
for (key of order) {
const item = list.find((obj) => obj.key == key);
if (item) newList.push(item);
}
return newList;
}
Вы можете использовать метод sort для массива. Метод sort будет сортировать на месте, поэтому вам следует скопировать свой массив, если вы не хотите изменять оригинал.
Метод массива sort
принимает функцию сравнения, которая получает два элемента для сравнения a
и b
. Он должен возвращать число и сортировать их в зависимости от этого числа:
> 0
, то b
стоит перед a
< 0
, то b
стоит после a
0
то оставить как естьИспользуя indexOf
в массиве newOrder
, можно получить индекс ключа. И индекс 0 должен идти раньше, и индекс 1 должен идти раньше, и индекс 2, конечно. Итак, если индекс a.key
равен 2, а индекс b.key
равен 0, то мы должны вернуть значение больше 0, поскольку b
должно стоять перед a
.
В моей реализации ниже я клонирую исходный список ([...list]
), чтобы случайно не мутировать. С тем же успехом вы могли бы сделать list.sort(...)
, если вам не нужно или не нужно мутировать.
const list = [{
key: "Name",
textColor: "red"
},{
key: "Age",
textColor: "green"
},{
key: "Occupation",
textColor: "yellow"
}]
const newOrder = ["Occupation", "Name", "Age"]
function sort(list, order) {
return [...list].sort((a, b) => {
const keyIndexA = order.indexOf(a.key);
const keyIndexB = order.indexOf(b.key);
if (keyIndexA < keyIndexB) return -1;
if (keyIndexA > keyIndexB) return 1;
return 0;
});
}
console.info(sort(list, newOrder));
Вы можете использовать обычный Сортировать
const list = [{key: "Name",textColor: "red"},{key: "Age",textColor: "green"},{key: "Occupation",textColor: "yellow"}];
const newOrder = ["Occupation", "Name", "Age"];
const result = list.sort(({key: a}, {key: b}) => newOrder.indexOf(a) - newOrder.indexOf(b));
console.info(result);
.as-console-wrapper{min-height: 100%!important; top: 0}
обратите внимание, что sort выполняет сортировку на месте, нет необходимости назначать новую переменную
Вы можете попробовать перебрать массив newOrder
, найти объект, который соответствует первому элементу, и нажать на новый массив.
const orderedList = [];
newOrder.forEach(order => {
orderedList.push(list.find(({key}) => key === order));
})
могут ли быть элементы с повторяющимся ключом