Как применить вложенную сортировку в javascript - PullRequest
3 голосов
/ 24 апреля 2019

У меня ниже array из objects в javascript

[
{'name' : 'Ram', 'age': 10 , 'city' : 'a'},
{'name' : 'Shyam', 'age': 5 , 'city' : 'a'},
{'name' : 'Aditya', 'age': 10 , 'city' : 'b'},
{'name' : 'Aditya', 'age': 5 , 'city' : 'a'}]

Теперь мне нужно применить вложенную сортировку.

Пользователь может отсортировать вышеуказанную коллекцию поимя, возраст, город.

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

[
{'name' : 'Aditya', 'age': 5 , 'city' : 'a'},
{'name' : 'Aditya', 'age': 10 , 'city' : 'b'}
{'name' : 'Mohan', 'age': 50 , 'city' : 'b'}
{'name' : 'Ram', 'age': 10 , 'city' : 'a'}]

Теперь пользователь нажимает для сортировки по возрасту (asc), но этоне должен мешать вышеуказанному массиву.

Он должен выглядеть одинаково

[
{'name' : 'Aditya', 'age': 5 , 'city' : 'a'},
{'name' : 'Aditya', 'age': 10 , 'city' : 'b'}
{'name' : 'Ram', 'age': 10 , 'city' : 'a'},
{'name' : 'Shyam', 'age': 5 , 'city' : 'a'}]

Но если предположить, что пользователь просит отсортировать сортировку выше по возрасту, чтобы он выглядел одинаково

 [
{'name' : 'Aditya', 'age': 10 , 'city' : 'a'},
{'name' : 'Aditya', 'age': 5 , 'city' : 'b'}
{'name' : 'Ram', 'age': 10 , 'city' : 'a'},
{'name' : 'Shyam', 'age': 5 , 'city' : 'a'}

Вот так выглядит моя текущая функция сортировки.

let compareObjects = (key, order = 'asc') => {
return function (a, b) {
    if (!a.hasOwnProperty(key) || !b.hasOwnProperty(key)) {
        // property doesn't exist on either object
        return 0;
    }

    const varA = (typeof a[key] === 'string') ?
        a[key].toUpperCase() : a[key];
    const varB = (typeof b[key] === 'string') ?
        b[key].toUpperCase() : b[key];

    let comparison = 0;
    if (varA > varB) {
        comparison = 1;
    } else if (varA < varB) {
        comparison = -1;
    }
    return (
        (order == 'desc') ? (comparison * -1) : comparison
    );
}}


 arrOfObjects.sort(compareObjects('age'));

Но я понятия не имею, как применить вложенную сортировку?

Спасибо!

Ответы [ 4 ]

1 голос
/ 24 апреля 2019

Метод compareObjects может принимать массив { key: order } объектов (sortBy). Затем зациклите массив sortBy с помощью for...of, извлеките ключ и порядок и сравните, пока результат не будет равен 0, или верните 0, если все они равны.

const compareStr = (a, b) => a.toLowerCase().localeCompare(b.toLowerCase())
const compareNumber = (a, b) => a - b

const compareBy = new Map([
  ['name', compareStr],
  ['age', compareNumber],
  ['city', compareStr],
])

const compareObjects = sortBy => (a, b) => {
  for (const srt of sortBy) { // iterate sortBy
    const [key, order] = Object.entries(srt)[0]; // extract key|order pairs
    const sorter = compareBy.get(key) // get the sorter from the Map

    if (!sorter || !(key in a) || !(key in b)) continue // if no sorter or if key doesn't exist in either object continue to the next sorter

    const score = sorter(a[key], b[key]) // sort the current values

    if (score === 0) continue; // if score is 0 continue to next sorter

    return score * (order === 'asc' ? 1 : -1) // return the score multiplied by -1 for non asc values
  }

  return 0;
}

const data = [{"name":"Ram","age":10,"city":"a"},{"name":"Shyam","age":5,"city":"a"},{"name":"Aditya","age":10,"city":"b"},{"name":"Aditya","age":5,"city":"a"}]

const result = data.sort(compareObjects([
  { age: 'desc' }, 
  { name: 'asc' }
]))

console.log(result)
1 голос
/ 24 апреля 2019

Array.prototype.sort() изменяет исходный массив.Он не копирует массив.

Возвращаемое значение

Сортированный массив.Обратите внимание, что массив отсортирован на месте, и копия не сделана .

Вы можете создать клон, используя оператор распространения. Оператор Spread сделает мелкую копию массива.

Другой способ улучшить код - использовать 1 и -1 вместо asc и desc и умножить его на результат обратного вызова sort().

Примечание: Оператор распространения будет делать только поверхностную копию, что означает, что объекты все еще будут иметь ссылку.Если вы хотите глубокое копирование, используйте JSON.parse(JSON.stringify())

const arr = [
  {'name' : 'Ram', 'age': 10 , 'city' : 'a'},
  {'name' : 'Shyam', 'age': 5 , 'city' : 'a'},
  {'name' : 'Aditya', 'age': 10 , 'city' : 'b'},
  {'name' : 'Aditya', 'age': 5 , 'city' : 'a'}
]

function sortBy(arr,key,order=1){
  arr = [...arr]
  return arr.sort((a,b) => (a[key] > b[key] ? 1 : -1) * order)
}

console.log(sortBy(arr,'name'))
console.log(sortBy(arr,'age',-1))
0 голосов
/ 24 апреля 2019

Вы также можете использовать sortBy из lodash .

const arr = [
  {'name' : 'Ram', 'age': 10 , 'city' : 'a'},
  {'name' : 'Shyam', 'age': 5 , 'city' : 'a'},
  {'name' : 'Aditya', 'age': 10 , 'city' : 'b'},
  {'name' : 'Aditya', 'age': 5 , 'city' : 'a'}
]

console.log('sortBy Name:', _.sortBy(arr, ['name']))
console.log('sortBy age:', _.sortBy(arr, ['age']))

console.log('sortBy City:', _.sortBy(arr, ['city']))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
0 голосов
/ 24 апреля 2019

Вам нужно сдать все критерии сортировки одновременно и вернуть отсортированный массив обратно.

В этом подходе используется массив массивов с ключами и направлением.Если направление не указано, я сортирую по возрастанию.

function sortBy(columns) {
    var cols = columns.map(([key, d]) => ({ key, dir: -(d === 'desc') || 1 }));
    return function (a, b) {
        var v;

        cols.some(({ key, dir }) => {
            var aVal = a[key],
                bVal = b[key];

            if (!a.hasOwnProperty(key) || !b.hasOwnProperty(key)) return v = 0;
            if (typeof aVal === 'string' && typeof bVal === 'string') {
                aVal = aVal.toUpperCase();
                bVal = bVal.toUpperCase();
            }
            return v = dir * (aVal > bVal || -(aVal < bVal));
        })

        return v;
    };
}

var data = [{ name: "Ram", age: 10, city: "a" }, { name: "Shyam", age: 5, city: "a" }, { name: "Aditya", age: 10, city: "b" }, { name: "Aditya", age: 5, city: "a" }]

console.log(data.sort(sortBy([['name'], ['age', 'desc']])));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...