2016-01-08 3 views
4

Я использую эту функцию для сортировки массива на основе ключа объекта:Сортировка массива по вложенной ключа

function keysrt(arr, key, reverse) { 
    var sortOrder = 1; 
    if(reverse){ 
     sortOrder = -1; 
    } 
    return arr.sort(function(a, b) { 
     var x = a[key], 
      y = b[key]; 

     return sortOrder * ((x < y) ? -1 : ((x > y) ? 1 : 0)); 
    }); 
} 

Это хорошо работает с этим типом массива, где ключ находится на первом уровне:

var a = [ 
    { id: 0, last: 'Anne'}, 
    { id: 1, last: 'Odine'}, 
    { id: 2, last: 'Caroline'} 
] 

keysrt(a, 'last'); 

Как я могу заставить его работать с этим примером, где ключ заголовка вложен?

var b = [ 
    { id: 0, last: 'Anne',  data:{title: 'habc'}}, 
    { id: 1, last: 'Odine', data:{title: 'asdf'}}, 
    { id: 2, last: 'Prentice', data:{title: 'tzuio'}} 
] 

keysrt(b, 'title'); 

ответ

6

Для этой идеи переменная «ключ» изменяется на массив ключей: Затем вы указываете «путь» к вложенному значению, которое хотите сортировать.

function keysrt(arr, keyArr, reverse) { 
    var sortOrder = 1; 
    if(reverse)sortOrder = -1; 
    return arr.sort(function(a, b) { 
     var x=a,y=b; 
     for (var i=0; i < keyArr.length; i++) { 
      x = x[keyArr[i]]; 
      y = y[keyArr[i]]; 
     } 
     return sortOrder * ((x < y) ? -1 : ((x > y) ? 1 : 0)); 
    }); 
} 

keysrt(b,['data','title']); 
0

Вы можете получить работу пример с помощью следующего кода:

function keysrt(arr, key, reverse) { 
    var sortOrder = reverse ? -1 : 1; 

    return arr.sort(function(a, b) { 
     var x,y; 

     if(typeof a[key] !== "undefined") { 
      x = a[key]; 
      y = b[key]; 
     } else { 
      for(var prop in a) { 
      if(a[prop][key] !== "undefined") { 
       x = a[prop][key]; 
       y = b[prop][key]; 
      } 
      } 
     } 

     return sortOrder * ((x < y) ? -1 : ((x > y) ? 1 : 0)); 
    }); 
} 

, но я хотел бы предложить более общее решение

function keysrt(arr, path, reverse) { 
    var sortOrder = reverse ? -1 : 1; 
    var pathSplitted = path.split("."); 

    if(arr.length <= 1) { 
     return arr; 
    } 

    return arr.sort(function(a, b) { 
     var x = a; 
     var y = b; 

     pathSplitted.forEach(function(key) { 
      x = x[key]; 
      y = y[key]; 
     });  

     return sortOrder * ((x < y) ? -1 : ((x > y) ? 1 : 0)); 
    }); 
} 

, в котором можно указать путь к сортировке поля как этот

var sorted = keysrt(b, 'data.title'); 

Демонстрация : http://jsbin.com/cosugawoga/edit?js,console

+0

Как один указать сортировку на 'title' элемент' data'? –

+0

Точно так же, как автор поставил под вопрос 'keysrt (b, 'title');'. –

3

Если вы готовы изменить сигнатуру функции и вызов функции, вот простой решение-

function keysrt(arr, prop, key, reverse) { 
    var sortOrder = 1; 
    if(reverse)sortOrder = -1; 
    return arr.sort(function(a, b) { 
     var x = a[prop][key]; var y = b[prop][key]; 
     return sortOrder * ((x < y) ? -1 : ((x > y) ? 1 : 0)); 
    }); 
} 


var b = [ 
    { id: 0, last: 'Anne',  data:{title: 'habc'}}, 
    { id: 1, last: 'Odine', data:{title: 'asdf'}}, 
    { id: 2, last: 'Prentice', data:{title: 'tzuio'}} 
] 

keysrt(b,'data', 'title'); 

Здесь prop представляет внешний объект, key будет представлять гнездовой ключ.

Так, var y = b[prop][key] будет в основном означает, что вы обращаетесь к b.data.title

Надеются, что это помогает :) Счастливым кодированию!

+0

Это не «прототип»; возможно, вы имели в виду «подпись». Как бы вы это расширили для обработки ключей на любом уровне вложенности? –

+0

Извините, отредактировал ответ. Да, я имел в виду подпись. И да, это одноуровневое. Для многоуровневого мы можем расширить «prop», чтобы быть массивом. или в основном решение «Джеймс» выглядит в этом случае довольно привлекательным! :) – bozzmob

2

Если вам нужно, чтобы сделать его универсальным, я думаю, что вы можете передать в функцию, которая будет извлекать значение из элемента массива для сравнения:

function keysrt(arr, reverse, getValueFn) { 
    var sortOrder = 1; 
    if(reverse)sortOrder = -1; 
    return arr.sort(function(a, b) { 
     var x = getValueFn(a); var y = getValueFn(b); 
     return sortOrder * ((x < y) ? -1 : ((x > y) ? 1 : 0)); 
    }); 
} 

Так что вы можете использовать его как:

keysrt(b, true, function(a){return a.data.title}) 
1

чтобы найти вложенное значение свойства, любое количество уровней вниз, вы можете использовать JSON.stringify как способ ходить объект:

function get_nested_value(obj, prop) { 
    var result; 
    JSON.stringify(obj, function(key, value) { 
    if (key === prop) result = value; 
    }); 
    return result; 
} 

Сейчас:

function keysrt(arr, key, reverse) { 
    var sortOrder = 1; 
    if(reverse){ 
     sortOrder = -1; 
    } 
    return arr.sort(function(a, b) { 
     var x = get_nested_value(a, key); 
      y = get_nested_value(b, key); 

     return sortOrder * ((x < y) ? -1 : ((x > y) ? 1 : 0)); 
    }); 
} 
Смежные вопросы