Сортировать массив по нескольким свойствам объекта в JavaScript - PullRequest
0 голосов
/ 26 июня 2018
var array  = [
    {
        "checked": true,
        "name":"Name",
        "type": {
            "id": 1,
            "tag": "tag"
        }
    },
    {
        "checked": true,
        "name":"Name",
        "type": {
            "id": 3,
            "tag": "tag"
        }
    },
    {
        "checked": false,
        "name":"Name",
        "type": {
            "id": 2,
            "tag": "tag"
        }
    },
];

Я хочу отсортировать массив по проверенному и type.id. Я использую следующий код сортировки, но, похоже, возникли проблемы с "type.id", так как мой список не сгруппирован по тем, которые отмечены.

sortByPriority(array, ['checked', 'type.id']);

sortByPriority(data, priorities) {
    if (priorities.length == 0 || data.length == 0) {
        return data;
    }
    const nextPriority = priorities[0];
    const remainingPriorities = priorities.slice(1);
    const matched = data.filter(item => item.hasOwnProperty(nextPriority));
    const remainingData = data.filter(item => !item.hasOwnProperty(nextPriority));

    return this.sortByPriority(matched, remainingPriorities)
        .sort((a, b) => (a[nextPriority] > b[nextPriority]) ? 1 : -1)
        .concat(this.sortByPriority(remainingData, remainingPriorities));
}

Есть идеи, как сортировать и объект типа?

(Мне не удалось найти другой вопрос с ответом с помощью универсального сортировщика, способного сортировать по объектам в массиве)

Ответы [ 3 ]

0 голосов
/ 26 июня 2018

Вот общее решение с использованием составных сортировок , в котором вы можете объединить произвольное количество условий сортировки в одну большую функцию сортировки:

    function to_tuples(array_of_elements) {
      return array_of_elements.map((element, index) => [element, index]);
    }
    function to_elements(array_of_tuples) {
      return array_of_tuples.map((element) => element[0]);
    }
    
    function compose_sorts(sort_functions) {
      const default_sort = (l, r) => l[1] < r[1];
    
      return sort_functions.reduceRight((master_sort, sort_function) => {

        const mixin = (next_sort, left, right) => {
          const result = sort_function(left, right);
          return result === 0 ? next_sort(left, right) : result;
        }
        return mixin.bind(null, master_sort); 
      }, default_sort);
    }

    function sort_checked_to_top(left_tuple, right_tuple) {
      const left = left_tuple[0];
      const right = right_tuple[0];
      if (left.checked !== right.checked) {
        return left.checked ? -1 : 1;
      }
      return 0;
    }
    
    function sort_lower_id_to_top(left_tuple, right_tuple) {
      const left = left_tuple[0];
      const right = right_tuple[0];
      if (left.type.id !== right.type.id) {
        return left.type.id > right.type.id ? 1 : -1;
      }
      return 0;
    }
    
    const master_sort = compose_sorts([
      sort_checked_to_top,
      sort_lower_id_to_top,      
    ]);
    
    var array  = [
    {
        "checked": true,
        "name":"Name",
        "type": {
            "id": 1,
            "tag": "tag"
        }
    },
    {
        "checked": false,
        "name":"Name",
        "type": {
            "id": 25,
            "tag": "tag"
        }
    },
    {
        "checked": true,
        "name":"Name",
        "type": {
            "id": 3,
            "tag": "tag"
        }
    },
    {
        "checked": false,
        "name":"Name",
        "type": {
            "id": 2,
            "tag": "tag"
        }
    },
];

const result = to_elements(to_tuples(array).sort(master_sort));
console.log(result);
    
    
    
0 голосов
/ 26 июня 2018

Вы можете использовать вложенный подход для вложенных свойств и использовать массив функций для сравнения значений.

function sortByPriority(array, keys, fn) {

    function getValue(o, k) {
        return k.split('.').reduce((p, l) => (p || {})[l], o);
    }

    return array.sort((a, b) => {
        var d;
        keys.some((k, i) => d = fn[i](getValue(a, k), getValue(b, k)));
        return d;
    });
}

var array = [{ checked: false, name: "Name", type: { id: 2, tag: "tag" } }, { checked: true, name: "Name", type: { id: 3, tag: "tag" } }, { checked: true, name: "Name", type: { id: 1, tag: "tag" } }];

sortByPriority(array, ['checked', 'type.id'], [(a, b) => b - a, (a, b) => a - b]);

console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }
0 голосов
/ 26 июня 2018

Перегрузите метод sort в массиве, и тогда вы можете просто переключать < и > в зависимости от условий сортировки. Обратите внимание, что я удалил return 0, если они равны в первой сортировке, чтобы перейти ко второй сортировке, если значения checked равны.

var array  = [
    {
        "checked": true,
        "name":"Name",
        "type": {
            "id": 1,
            "tag": "tag"
        }
    },
    {
        "checked": true,
        "name":"Name",
        "type": {
            "id": 3,
            "tag": "tag"
        }
    },
    {
        "checked": false,
        "name":"Name",
        "type": {
            "id": 2,
            "tag": "tag"
        }
    },
];

function customSort(ob1, ob2) {
    if (ob1.checked > ob2.checked) {
        return 1;
    } else if (ob1.checked < ob2.checked) { 
        return -1;
    }

    // Else sort on the second item
    if (ob1.type.id < ob2.type.id) { 
        return -1;
    } else if (ob1.type.id > ob2.type.id) {
        return 1
    } else {
        return 0;
    }
}

console.log(array);
console.log(array.sort(customSort));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...