2015-11-26 4 views
3

У меня есть коллекция имен:Сортировать коллекцию другого массива

[ 
    {last_name: "A", name: "James" }, 
    {last_name: "A", name: "Robert" }, 
    {last_name: "B", name: "Tim"}, 
    {last_name: "B", name: "Bob" }, 
    {last_name: "C", name: "Ricky Ticky" } 
] 

Тогда у меня есть массив с каждым last_name в нем, в определенном порядке:

["B", "C", "A"] 

Как я могу сортировать моя коллекция по порядку last_names в моем втором массиве?

Что я пробовал:

Лучшее решение, которое я до сих пор, чтобы создать новый массив, а затем цикл через мою коллекцию имен, выдвигая все элементы, которые соответствуют индексу моего SORT массива («B»), затем второй индекс («C») и, наконец, «A». Кажется, многословный или, может быть, underscore.js имеет лучший метод. sortBy функция

ответ

6

Используйте Underscore, в том, что дает возможность сортировать по произвольной функции элементов массива:

var people = [ 
 
    {last_name: "A", name: "James" }, 
 
    {last_name: "A", name: "Robert" }, 
 
    {last_name: "B", name: "Tim"}, 
 
    {last_name: "B", name: "Bob" }, 
 
    {last_name: "C", name: "Ricky Ticky" } 
 
]; 
 

 
var lastNameOrder = ["B", "C", "A"]; 
 

 
var sortedPeople = _.sortBy(people, function(person) { 
 
    return lastNameOrder.indexOf(person.last_name); 
 
}) 
 

 
console.log(sortedPeople);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script> 
 
<!-- results pane console output; see http://meta.stackexchange.com/a/242491 --> 
 
<script src="http://gh-canon.github.io/stack-snippet-console/console.min.js"></script>

+0

Вы также может сделать один проход над 'lastNameOrder', чтобы построить карту индексов name-> в' Object', а затем использовать этот 'Object' в функции' _.sortBy'. Возможно, это будет быстрее, возможно, нет, возможно, даже не заметно с такими небольшими наборами данных. –

+0

@muistooshort: Это почти то, что делает '_.sortBy' - я бы повторил его работу. (Это также является причиной моего первого комментария о реализации Брэди.) – Amadan

+0

Не совсем. Шварцское преобразование, которое 'sortBy' делает, вызовет' indexOf' 'people.length' раз. Если вы построите карту имени-> индекс вручную, вы бы вообще не назовете 'indexOf', вы просто сделаете один проход через' lastNameOrder', а не линейный поиск 'people.length'; вы в конечном итоге выполняете поиск 'people.length' в индексном объекте name-> вместо всех этих вызовов' indexOf'. –

1

Это можно сделать довольно просто с Array.sort() ,

function sortNames(names, order) { 
    return names.sort(function(a,b) { 
    if (order.indexOf(a.last_name) > order.indexOf(b.last_name)) return 1; 
    return 0; 
    }); 
} 

Array.prototype.sort() сортирует ваш массив путем сравнения двух значений за раз. если вы вернетесь 1, b появится перед a; -1, a до b; и ноль не меняется.

более

информация на https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

+0

выкачайте необработанный JS - теперь попробуйте –

+1

Это медленнее реализации Underscore, поскольку он вызывает 'indexOf' при каждом сравнении (вероятно,' O (n log (n)) '), а Underscore вызывает его один раз для элемента (' O (п) '). – Amadan

+0

Выполните анализ алгоритма - в моем случае скорость не имеет значения (малый массив), но хорошо знать –

1

Отредактировано: из-за серьезного сбоя

Но это еще не сортирует имена и потому, что я не вижу никаких причин, чтобы не сделать так

var people = [ 
    {last_name: "A", name: "James" }, 
    {last_name: "A", name: "Robert" }, 
    {last_name: "B", name: "Tim"}, 
    {last_name: "B", name: "Bob" }, 
    {last_name: "C", name: "Ricky Ticky" } 
]; 

var lastNameOrder = ["B", "C", "A"]; 

var sortedPeople = people.sort(function(person1,person2){ 
    var lna = lastNameOrder.indexOf(person1.last_name); 
    var lnb = lastNameOrder.indexOf(person2.last_name); 

    if(lna === lnb){ 
    return (person1.name < person2.name) ? -1 : 
      (person1.name > person2.name) ? 1 : 0; 
    } else { 
    return lna-lnb; 
    } 
}) 
+1

JS требует функцию компаратора; 'sort (function (element) {...})' неверен. Если вы получили правильный результат, это совпадение; попробуйте его с помощью другого 'lastNameOrder'. – Amadan

+0

Yepp, это правда, я не тестировал его полностью. Даже у моего второго примера была ошибка! – deamentiaemundi

Смежные вопросы