it-swarm.com.ru

Сортировать массив по значению ключа

У меня есть функция, которая сортирует по имени в настоящее время и массив пар значение/ключ.

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

var arr = [{name:'bob', artist:'rudy'},
           {name:'johhny', artist:'drusko'},
           {name:'tiff', artist:'needell'},
           {name:'top', artist:'gear'}];

sort(arr, 'name');   //trying to sort by name
sort(arr, 'artist'); //trying to sort by artist

function sort(arr) {
  arr.sort(function(a, b) {
    var nameA=a.name.toLowerCase(), nameB=b.name.toLowerCase();
    if (nameA < nameB) //sort string ascending
      return -1;
    if (nameA > nameB)
      return 1;
    return 0; //default return value (no sorting)
   });          
}
16
Toniq

Вот две функции сортировки, которые могут быть полезны:

// sort on values
function srt(desc) {
  return function(a,b){
   return desc ? ~~(a < b) : ~~(a > b);
  };
}

// sort on key values
function keysrt(key,desc) {
  return function(a,b){
   return desc ? ~~(a[key] < b[key]) : ~~(a[key] > b[key]);
  }
}

Для вашего массива вы можете отсортировать по имени, используя:

var arr = [ {name:'bob', artist:'rudy'}
           ,{name:'johhny', artist:'drusko'}
           ,{name:'tiff', artist:'needell'}
           ,{name:'top', artist:'gear'}]
          .sort(keysrt('name'));

Вы также можете объединить функции сортировки:

function srt(desc,key) {
 return function(a,b){
   return desc ? ~~(key ? a[key]<b[key] : a < b) 
               : ~~(key ? a[key] > b[key] : a > b);
  };
}

И использовать

var arr = [ {name:'bob', artist:'rudy'}
               ,{name:'johhny', artist:'drusko'}
               ,{name:'tiff', artist:'needell'}
               ,{name:'top', artist:'gear'}]
              .sort(srt(null,'name'));

Вот что-то типа «все в одном»:

function srt(on,descending) {
 on = on && on.constructor === Object ? on : {};
 return function(a,b){
   if (on.string || on.key) {
     a = on.key ? a[on.key] : a;
     a = on.string ? String(a).toLowerCase() : a;
     b = on.key ? b[on.key] : b;
     b = on.string ? String(b).toLowerCase() : b;
     // if key is not present, move to the end 
     if (on.key && (!b || !a)) {
      return !a && !b ? 1 : !a ? 1 : -1;
     }
   }
   return descending ? ~~(on.string ? b.localeCompare(a) : a < b)
                     : ~~(on.string ? a.localeCompare(b) : a > b);
  };
}
// usage examples
'a,z,x,y,a,b,B,Z,a,i,j,y'.split(',').sort( srt({string:true;}) );
 //=> ,a,a,b,B,i,j,x,y,y,z,Z
[100,7,8,2,2,0,5,1,6,5,-1].sort( srt() );
 //=> -1,0,1,2,2,5,5,6,7,8,100
[100,7,8,2,2,0,5,1,6,5,-1].sort( srt({},true}) );
 //=> 100,8,7,6,5,5,2,2,1,0,-1
var objarr = 
 [ {name:'bob', artist:'rudy'}
  ,{name:'Johhny', artist:'drusko'}
  ,{name:'Tiff', artist:'needell'}
  ,{name:'top', artist:'gear'}]
 .sort( srt({key:'name',string:true}, true) );
for (var i=0;i<objarr.length;i+=1) {
  console.log(objarr[i].name);
}
//=> logs zeb, top, Tiff, Johnny consecutively
19
KooiInc
Array.prototype.sortOn = function(key){
    this.sort(function(a, b){
        if(a[key] < b[key]){
            return -1;
        }else if(a[key] > b[key]){
            return 1;
        }
        return 0;
    });
}



var arr = [{name:'bob', artist:'rudy'},{name:'johhny', artist:'drusko'},{name:'tiff', artist:'needell'},{name:'top', artist:'gear'}];

arr.sortOn("name");
arr.sortOn("artist");
41
Diode
function keysrt(key) {
  return function(a,b){
   if (a[key] > b[key]) return 1;
   if (a[key] < b[key]) return -1;
   return 0;
  }
}

someArrayOfObjects.sort(keysrt('text'));
6
Phaedrus

Сделайте свою жизнь проще и используйте закрытие https://stackoverflow.com/a/31846142/1001405

Вы можете увидеть рабочий пример здесь

var filter = 'name', //sort by name
data = [{name:'bob', artist:'rudy'},{name:'johhny', artist:'drusko'},{name:'tiff', artist:'needell'},{name:'top', artist:'gear'}];; 

var compare = function (filter) {
    return function (a,b) { //closure
        var a = a[filter],
            b = b[filter];

        if (a < b) {
            return -1;
        }else if (a > b) {
            return 1;
        } else {
            return 0;
        }
    };
};

filter = compare(filter); //set filter

console.log(data.sort(filter));
2
Michael Guild

Посмотрев на все ответы, я нашел собственное решение, которое работает в кросс-браузерном режиме. Принятое решение не работает в IE или Safari. Также другие решения не позволяют сортировку по убыванию.

/*! FUNCTION: ARRAY.KEYSORT(); **/
Array.prototype.keySort = function(key, desc){
  this.sort(function(a, b) {
    var result = desc ? (a[key] < b[key]) : (a[key] > b[key]);
    return result ? 1 : -1;
  });
  return this;
}

var arr = [{name:'bob', artist:'rudy'}, {name:'johhny', artist:'drusko'}, {name:'tiff', artist:'needell'}, {name:'top', artist:'gear'}];
arr.keySort('artist');
arr.keySort('artist', true);
0
Jake