it-swarm-pt.tech

Alguma maneira de estender o método array.sort () do javascript para aceitar outro parâmetro?

Estou tentando classificar uma matriz de objetos. Prefiro não escrever um método de classificação personalizado para cada atributo.

Existe alguma maneira de estender o método interno array.sort() para aceitar um parâmetro extra, descrevendo o atributo para classificar? Por exemplo.,

array.sort(function(a, b, attr) { return a.attr - b.attr; }, 'name');
54
danwoods

Escreva um gerador de função que aceite um nome de propriedade:

function propComparator(prop) {
    return function(a, b) {
        return a[prop] - b[prop];
    }
}

arr.sort(propComparator('name'));

Você também pode salvar os classificadores para uso posterior, diretamente ou como parâmetros:

var compareNames = propComparator('name');
var compareFoos = propComparator('foo');
...
arr.sort(compareNames);
takesComparator(compareFoos);

Atualizado para ES6 e torná-lo realmente funciona com tipos diferentes.

Observe que sort classifica no local, o que pode ou não ser desejável.

const arr = [
  { name: 'John', age: 92 },
  { name: 'Dave', age: 42 },
  { name: 'Justin', age: 3 }
]

const propComparator = (propName) =>
  (a, b) => a[propName] == b[propName] ? 0 : a[propName] < b[propName] ? -1 : 1

arr.sort(propComparator('name'))
console.log("By name", arr)

arr.sort(propComparator('age'))
console.log("By age", arr)
110
Dave Newton

É isso que você está procurando?

function sortByProperty(array, propertyName) {
    return array.sort(function (a, b) {
        return a[propertyName] - b[propertyName];
    });
}

var sortedByName = sortByProperty(myArray, "name");
8
Domenic

Use protótipos para comparar sequências e números corretamente

Array.prototype.sortAttr = function(attr,reverse) {
  var sorter = function(a,b) {
    var aa = a[attr];
    var bb = b[attr];
    if(aa+0==aa && bb+0==bb) return aa-bb; // numbers
    else return aa.localeCompare(bb); // strings
  }
  this.sort(function(a,b) {
    var result = sorter(a,b);
    if(reverse) result*= -1;
    return result;
  });
};

Exemplo

var data = [
  {name: "Josh", age: 18},
  {name: "John", age: 17},
  {name: "Bob", age: 20},
  {name: 0, age: "error"}
];

data.sortAttr("name");
// data is now sorted by name
4
Jan Turoň

Existe alguma maneira de estender o método array.sort () interno para aceitar um parâmetro extra

todas as respostas acima são boas. mas pensei em adicionar algumas informações sobre funções parciais

para obter mais informações, consulte bind no MDN e função parcial ou John Resig - função parcial

Exemplo do MDN:

function list() {
  return Array.prototype.slice.call(arguments);
}

var list1 = list(1, 2, 3); // [1, 2, 3]

//  Create a function with a preset leading argument
var leadingThirtysevenList = list.bind(undefined, 37);

var list2 = leadingThirtysevenList(); // [37]
var list3 = leadingThirtysevenList(1, 2, 3); // [37, 1, 2, 3]

aqui está um exemplo de Google Closure

goog.partial = function(fn, var_args) {
  var args = Array.prototype.slice.call(arguments, 1);
  return function() {
    // Prepend the bound arguments to the current arguments.
    var newArgs = Array.prototype.slice.call(arguments);
    newArgs.unshift.apply(newArgs, args);
    return fn.apply(this, newArgs);
  };
};

usar esta função

    var fn=goog.partial(numberCompare,sortField,sortDirection);
    myarray.sort (fn);


    var numberCompare = function (sortField,sortDirection,value1,value2){
      // sort code goes here
    }
3
dekdev

Caso alguém precise de ordem crescente, aqui está a solução de DaveNewton com uma opção reversa

const sorton = (prop, asc=0) => {
    if(!asc) return (a, b) => a[prop] == b[prop] ? 0 : a[prop] < b[prop] ? -1 : 1
    else return (b, a) => a[prop] == b[prop] ? 0 : a[prop] < b[prop] ? -1 : 1
}

arr.sort(propComparator('age', 1))

1
stallingOne