Classificando a propriedade do objeto por valores


696

Se eu tiver um objeto JavaScript como:

var list = {
  "you": 100, 
  "me": 75, 
  "foo": 116, 
  "bar": 15
};

Existe uma maneira de classificar as propriedades com base no valor? Para que eu acabe com

list = {
  "bar": 15, 
  "me": 75, 
  "you": 100, 
  "foo": 116
};

4
Não apenas "classificando", mas mais importante classificando números. Os números são imunes ao método Javascripts Array.sort (), o que significa que você não precisará apenas encontrar um método para classificar propriedades, mas precisará escrever sua própria função para comparar os valores numéricos.
Sampson

106
Antes de ler as respostas: A resposta é Não . A ordem das propriedades do objeto não é padrão no ECMAScript. Você nunca deve fazer suposições sobre a ordem dos elementos em um objeto JavaScript. Um objeto é uma coleção não ordenada de propriedades. As respostas abaixo mostram como "usar" propriedades classificadas, usando a ajuda de matrizes, mas nunca alterando a ordem das propriedades dos próprios objetos. Então, não, não é possível. Mesmo se você criar um objeto com propriedades predefinidas, não é garantido que eles sejam exibidos na mesma ordem no futuro. Leia :).
Govind Rai

3
@GovindRai ainda, em aplicativos de front-end do mundo real, percorremos coleções de objetos com IDs como chaves e a ordem é importante se traduzida para modelos HTML. Você diz que eles não têm ordem, eu digo que eles têm exatamente a ordem que eu vejo ao console.logando-os no navegador atual. E essa ordem pode ser reordenada. Assim que você passa por cima deles, eles têm um pedido.
ProblemsOfSumit

7
@GovindRai: Agora existe um meio de acessar propriedades em uma ordem especificada na especificação. É uma boa ideia? Quase certamente não. :-) Mas está lá, a partir do ES2015.
TJ Crowder

7
Visitantes de 2019: verifique esta Object.entriesresposta mal votada, que é o estado da arte mais limpo e legível desde o ES2017: stackoverflow.com/a/37607084/245966
jakub.g

Respostas:


705

Mova-os para uma matriz, classifique essa matriz e use-a para seus propósitos. Aqui está uma solução:

var maxSpeed = {
    car: 300, 
    bike: 60, 
    motorbike: 200, 
    airplane: 1000,
    helicopter: 400, 
    rocket: 8 * 60 * 60
};
var sortable = [];
for (var vehicle in maxSpeed) {
    sortable.push([vehicle, maxSpeed[vehicle]]);
}

sortable.sort(function(a, b) {
    return a[1] - b[1];
});

//[["bike", 60], ["motorbike", 200], ["car", 300],
//["helicopter", 400], ["airplane", 1000], ["rocket", 28800]]

Depois de ter a matriz, você poderá reconstruir o objeto a partir da matriz na ordem que desejar, atingindo exatamente o que deseja fazer. Isso funcionaria em todos os navegadores que eu conheço, mas seria dependente de uma peculiaridade de implementação e poderia ser interrompida a qualquer momento. Você nunca deve fazer suposições sobre a ordem dos elementos em um objeto JavaScript.

var objSorted = {}
sortable.forEach(function(item){
    objSorted[item[0]]=item[1]
})

24
Você pode reformular "você pode reconstruir" para "você pode usar a matriz para manter a ordem das chaves e extrair valores do objeto"? Além de não ser padrão, como você mesmo mencionou, essa suposição errônea é quebrada por mais navegadores do que apenas o Chrome hoje, por isso é melhor não incentivar os usuários a experimentá-lo.
amigos estão dizendo sobre oleg V.

32
Aqui está uma versão mais compacta do seu código. Object.keys (maxSpeed) .sort (função (a, b) {return - (maxSpeed ​​[a] - maxSpeed ​​[b])});
TheBrain 12/12/12

6
@TheBrain: Só para adicionar, keys()é suportado apenas pelo IE9 + (e outros navegadores modernos), se isso for motivo de preocupação. Também keys()exclui propriedades enumeráveis ​​da cadeia de protótipos dos elementos (diferente de..in) - mas isso geralmente é mais desejável.
MrWhite

31
_.pairstransforma um objeto em [[chave1, valor1], [chave2, valor2]]. Então chame uma ordem sobre isso. Depois, ligue _.object-o para voltar.
21814 Funkodebat

2
Meu projeto requer chaves de objeto para mesclar corretamente, mas também exige classificação explícita, pois os metadados direcionam a interface do usuário. Segui uma abordagem semelhante, apenas adicionei uma verificação hasOwnProperty para evitar o rastreamento da cadeia de protótipos. Aqui está um bom artigo sobre iteração sobre as propriedades do objeto em JS hackernoon.com/...
Nathan Agersea

416

Não queremos duplicar toda a estrutura de dados ou usar uma matriz em que precisamos de uma matriz associativa.

Aqui está outra maneira de fazer a mesma coisa que bonna:

var list = {"you": 100, "me": 75, "foo": 116, "bar": 15};
keysSorted = Object.keys(list).sort(function(a,b){return list[a]-list[b]})
console.log(keysSorted);     // bar,me,you,foo


22
Isso parece estar classificando por chave, não por valor, o que não é o que a pergunta pedia?
Michael Michael

27
Ele é classificado por valor e exibe chaves - mas perdemos a contagem do valor quando ele é impresso, pois imprime apenas as chaves.
2122 Hanna

6
A ordem das propriedades do objeto não é garantida no JavaScript, portanto, a classificação deve ser feita em uma matriz, não em um objeto (que é o que você está chamando de 'matriz associativa').
Christopher Meyers

6
Não se esqueça keysSortedé uma matriz! Não é um objeto!
Verde

17
Se você adicionar .map(key => list[key]);ao final da classificação, ele retornará o objeto inteiro em vez de apenas a chave
James Moran

183

Seus objetos podem ter qualquer quantidade de propriedades e você pode optar por classificar por qualquer propriedade de objeto que desejar, número ou sequência, se colocar os objetos em uma matriz. Considere esta matriz:

var arrayOfObjects = [   
    {
        name: 'Diana',
        born: 1373925600000, // Mon, Jul 15 2013
        num: 4,
        sex: 'female'
    },
    {

        name: 'Beyonce',
        born: 1366832953000, // Wed, Apr 24 2013
        num: 2,
        sex: 'female'
    },
    {            
        name: 'Albert',
        born: 1370288700000, // Mon, Jun 3 2013
        num: 3,
        sex: 'male'
    },    
    {
        name: 'Doris',
        born: 1354412087000, // Sat, Dec 1 2012
        num: 1,
        sex: 'female'
    }
];

ordenar por data de nascimento, mais antiga primeiro

// use slice() to copy the array and not just make a reference
var byDate = arrayOfObjects.slice(0);
byDate.sort(function(a,b) {
    return a.born - b.born;
});
console.log('by date:');
console.log(byDate);

ordenar por nome

var byName = arrayOfObjects.slice(0);
byName.sort(function(a,b) {
    var x = a.name.toLowerCase();
    var y = b.name.toLowerCase();
    return x < y ? -1 : x > y ? 1 : 0;
});

console.log('by name:');
console.log(byName);

http://jsfiddle.net/xsM5s/16/


1
Classificar por nome não deve substrsair do primeiro caractere; mais Dianae Debrater uma ordem indefinida. Além disso, sua byDateclassificação realmente usa num, não born.
Lawrence Dol

Este parece ser bom, mas nota que para comparar strings você pode apenas usarx.localeCompare(y)
Jemar Jones

2
@JemarJones localCompareparece uma função muito útil! Observe que ele não será suportado em todos os navegadores - IE 10 e menos, Safari Mobile 9 e menos.
inorganik

@inorganik Sim nota muito boa para aqueles que precisam para apoiar os navegadores
Jemar Jones

1
Esta é uma disposição de objectos, que não é a OP requisitado (um objecto com várias propriedades)
João Pimentel Ferreira

62

Para completar, essa função retorna uma matriz classificada de propriedades do objeto:

function sortObject(obj) {
    var arr = [];
    for (var prop in obj) {
        if (obj.hasOwnProperty(prop)) {
            arr.push({
                'key': prop,
                'value': obj[prop]
            });
        }
    }
    arr.sort(function(a, b) { return a.value - b.value; });
    //arr.sort(function(a, b) { a.value.toLowerCase().localeCompare(b.value.toLowerCase()); }); //use this to sort as strings
    return arr; // returns array
}

var list = {"you": 100, "me": 75, "foo": 116, "bar": 15};
var arr = sortObject(list);
console.log(arr); // [{key:"bar", value:15}, {key:"me", value:75}, {key:"you", value:100}, {key:"foo", value:116}]

O Jsfiddle com o código acima está aqui . Esta solução é baseada neste artigo .

O violino atualizado para classificar strings está aqui. Você pode remover ambas as conversões adicionais .toLowerCase () para comparação de cadeias que diferenciam maiúsculas de minúsculas.


1
E quanto a uma matriz de objetos? [{nome: Will}, {nome: Bill}, {nome: Ben}]
Will Hancock

1
Oi Will, você pode usar a função localeCompare para essa comparação. Adicionado à resposta acima.
Stano

Ótima solução. A seqüência de tipo precisa de um retorno
pfwd

@Stano Solução correta e simples. Muito obrigado.
Abrar Hossain

48

Introduz ECMAScript 2017 Object.values / Object.entries. Como o nome sugere, o primeiro agrega todos os valores de um objeto em uma matriz, e o último faz o objeto inteiro em uma matriz de [key, value]matrizes; O equivalente em Python de dict.values()e dict.items().

Os recursos tornam muito mais fácil classificar qualquer hash em um objeto ordenado. A partir de agora, apenas uma pequena parte das plataformas JavaScript as suporta , mas você pode experimentá-lo no Firefox 47 ou superior.

let obj = {"you": 100, "me": 75, "foo": 116, "bar": 15};

let entries = Object.entries(obj);
// [["you",100],["me",75],["foo",116],["bar",15]]

let sorted = entries.sort((a, b) => a[1] - b[1]);
// [["bar",15],["me",75],["you",100],["foo",116]]

como isso possivelmente responde ao título da pergunta Sorting JavaScript Object by property value? você entendeu mal a pergunta, pois você deve alterar o objeto original e não criar uma nova matriz a partir dele.
vsync 14/06

2
@vsync Esta resposta fornece o mesmo resultado que a resposta aceita, mas com menos código e nenhuma variável temporária.
Darren Cozinhe

3
FWIW, esta resposta é clara e é a única que me ajudou.
NetOperator Wibby

somente em ff, não ie, nem no chrome mais eles classificam os objetos automaticamente. wtf
fb

Observe que isso não preservará as chaves.
Vael Victus

40

Uma versão "em flecha" da resposta de @marcusR para referência

var myObj = {"you": 100, "me": 75, "foo": 116, "bar": 15};
keysSorted = Object.keys(myObj).sort((a,b) => myObj[a]-myObj[b])
alert(keysSorted);     // bar,me,you,foo

ATUALIZAÇÃO: abril de 2017 - Retorna um myObjobjeto classificado definido acima.

Object
 .keys(myObj)
 .sort((a, b) => myObj[a]-myObj[b])
 .reduce((_sortedObj, key) => ({
   ..._sortedObj, 
   [key]: myObj[key]
 }), {})

Experimente aqui!

ATUALIZAÇÃO: outubro de 2018 - versão Object.entries

Object
 .entries(myObj)
 .sort()
 .reduce((_sortedObj, [k,v]) => ({
   ..._sortedObj, 
   [k]: v
 }), {})

Experimente aqui!


1
não funciona paravar myObj = {"1": {"Value": 40}, "2": {"Value": 10}, "3": {"Value": 30}, "4": {"Value": 20}};
Rohanil

5
A pergunta do OP, juntamente com esta resposta, não contém objetos aninhados @Rohanil Talvez você queira fazer outra pergunta em vez de fazer uma votação negativa. Seu objeto aninhado com vários tipos precisa, obviamente, mais do que esta solução oferece
Jason J. Nathan

Apenas uma observação: suas atualizações não funcionarão realmente. Pelo menos não em toda parte e não por causa de entries. De acordo com o padrão, um objeto é uma coleção não ordenada de propriedades . Bem, isso significa que se você estiver tentando construir o novo objeto depois de classificá-lo por valor da propriedade ou qualquer outra coisa, a ordem das chaves de propriedade se tornará indefinida novamente. O Chrome, por exemplo, está ordenando por padrão as chaves de propriedade; portanto, todas as tentativas de solicitá-las de maneira diferente são inúteis. Sua única chance é obter um "índice" com base nas suas preferências de pedido e percorrer o objeto original de acordo.
ZorgoZ 25/10

Sim @ZorgoZ, você está certo e muitas pessoas mencionaram isso neste post. Na maioria das vezes, usamos essa função como uma transformação antes de converter para outro tipo (como JSON) ou antes de outra função de redução. Se o objetivo for alterar o objeto posteriormente, poderá haver resultados inesperados. Eu tive sucesso com essa função em todos os mecanismos.
Jason J. Nathan

Nota: você não quiser usar sort()emObject.entries()
Solvitieg

36

Os objetos JavaScript não são ordenados por definição (consulte a Especificação de idioma do ECMAScript , seção 8.6). A especificação da linguagem nem garante que, se você iterar sobre as propriedades de um objeto duas vezes seguidas, elas serão exibidas na mesma ordem na segunda vez.

Se você precisar solicitar itens, use uma matriz e o método Array.prototype.sort.


4
Observe que houve muita discussão sobre isso. A maioria das implementações mantém a lista na ordem em que os elementos foram adicionados. IIRC, o Chrome não. Houve uma discussão sobre se o Chrome deveria se alinhar com as outras implementações. Minha crença é que um objeto JavaScript é um hash e nenhuma ordem deve ser assumida. Acredito que o Python passou pelo mesmo argumento e uma nova lista ordenada de hash foi introduzida recentemente. Para a maioria dos navegadores, você PODE fazer o que deseja, recriando seu objeto, adicionando elementos por valor classificado. Mas você não deveria.
Nosredna

Editar. O Chrome normalmente mantém a ordem, mas nem sempre. E aqui está o bug cromo relevante: code.google.com/p/chromium/issues/detail?id=883
Nosredna

6
Esse relatório de erros é injustificado, e aqueles que se basearam no comportamento não documentado são os que apresentam os erros. Leia a seção 8.6 do ECMASCript; afirma claramente que "Um objeto é uma coleção não ordenada de propriedades". Qualquer um que descobrisse que isso não parecia assim em algumas implementações e que depois começou a depender desse comportamento específico da implementação, cometeu um grande erro e não deveria estar tentando desviar a culpa de si. Se eu estivesse na equipe do Chrome, marcaria esse relatório de erro como "Inválido, WontFix".
244 NickFitz

8
O EcmaScript 5 realmente define a ordem de enumeração como a ordem de inserção - a ausência de definição é considerada um bug de especificação no ES3. Vale a pena notar que a especificação do EcmaScript define um comportamento que ninguém consideraria sensato - por exemplo, o comportamento da especificação é que, em muitos casos, erros de sintaxe são gerados em tempo de execução, uso incorreto de continue, pausa, ++, -, const, etc. com a especificação de qualquer motor que gera uma exceção antes de chegar a esse código é errado
olliej

4
@olliej - Eu não acho que isso esteja correto. A especificação diz: "A mecânica e a ordem de enumerar as propriedades (etapa 6.a no primeiro algoritmo, etapa 7.a no segundo) não estão especificadas". Isso está na página 92 ​​do PDF do rascunho final.
whitneyland

25

OK , como você deve saber, o javascript possui sort () função , para ordenar matrizes, mas nada para o objeto ...

Portanto, nesse caso, precisamos, de alguma forma, obter a matriz das chaves e classificá-las, e é por isso que a API fornece objetos em uma matriz na maioria das vezes, porque a matriz tem mais funções nativas para brincar com elas do que o objeto literal, de qualquer maneira, a solução rápida está usando Object.key, que retorna uma matriz das chaves de objeto, eu crio a função ES6 abaixo, que faz o trabalho para você, ele usa funções nativas de classificação () e de redução () em javascript:

function sortObject(obj) {
  return Object.keys(obj)
    .sort().reduce((a, v) => {
    a[v] = obj[v];
    return a; }, {});
}

E agora você pode usá-lo assim:

let myObject = {a: 1, c: 3, e: 5, b: 2, d: 4};
let sortedMyObject = sortObject(myObject);

Verifique o selectedMyObject e você poderá ver o resultado classificado por chaves como esta:

{a: 1, b: 2, c: 3, d: 4, e: 5}

Além disso, o objeto principal não será tocado e, na verdade, estamos recebendo um novo objeto.

Também crio a imagem abaixo, para tornar as etapas da função mais claras, caso você precise alterá-la um pouco para que funcione do seu jeito:

Classificando um objeto javascript por valor da propriedade


4
Essa classificação por chave, não por valor.
ROROROOROROR 28/08

@ROROROOROROR, é apenas uma indicação de como funciona, pois eles não são tão diferentes, mas tudo bem, vou adicionar também a classificação por valor
Alireza

1
A classificação por valor está incorreta e é o seu conjunto de dados. Mude c: 3para c: 13e você verá desmoronar.
VtoCorleone

1
@VtoCorleone Esse é apenas um erro de classificação natural, o primeiro é o primeiro, não uma falha no algoritmo, como apresentado.
precisa saber é o seguinte

10
var list = {
    "you": 100, 
    "me": 75, 
    "foo": 116, 
    "bar": 15
};

function sortAssocObject(list) {
    var sortable = [];
    for (var key in list) {
        sortable.push([key, list[key]]);
    }
    // [["you",100],["me",75],["foo",116],["bar",15]]

    sortable.sort(function(a, b) {
        return (a[1] < b[1] ? -1 : (a[1] > b[1] ? 1 : 0));
    });
    // [["bar",15],["me",75],["you",100],["foo",116]]

    var orderedList = {};
    for (var idx in sortable) {
        orderedList[sortable[idx][0]] = sortable[idx][1];
    }

    return orderedList;
}

sortAssocObject(list);

// {bar: 15, me: 75, you: 100, foo: 116}

Simples e perfeito! Isso responde à pergunta. Obrigado.
precisa

Ordem da chave não é garantida em javascript assim que esta falha para mim se as chaves são inteiros ou similar
Parox

exato, ParoX. Isso não está funcionando corretamente quando a chave é do tipo inteiro.
Jungwon jin

8

Atualização com o ES6: se sua preocupação é ter um objeto classificado para percorrer (e é por isso que eu imagino que você deseja que suas propriedades sejam classificadas), você pode usar o objeto Map .

Você pode inserir seus pares (chave, valor) na ordem classificada e, em seguida, fazer um for..ofloop garantirá que eles façam loop na ordem em que foram inseridos

var myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
for (var [key, value] of myMap) {
  console.log(key + " = " + value);
}
// 0 = zero 
// 1 = one

Também no ES6 (ES2015): As propriedades do objeto têm ordem (ou existe um meio de acessá-las em uma ordem definida, dependendo do seu ponto de vista). Se os nomes das propriedades forem cadeias de caracteres e não se parecerem com índices de matriz, a ordem será a ordem em que foram adicionados ao objeto. Esse pedido não está especificado para ser respeitado por for-inou Object.keys, mas está definido para ser respeitado por Object.getOwnPropertyNamese pelos outros novos métodos para acessar matrizes de nomes de propriedades. Então essa é outra opção.
TJ Crowder

Mas onde está a operação 'classificar'? Eles não são classificados de maneira alguma #
066

@ Green Eu acho que o que eu queria destacar aqui é que, com Mapvocê, na verdade , você tem uma estrutura de dados que pode armazenar em ordem classificada (classifique seus dados, faça um loop e armazene-os no mapa) onde, como você não está garantido, objetos.
21717 Julianljk

6

Underscore.js ou Lodash.js para classificações avançadas de matriz ou objeto

 var data={
        "models": {

            "LTI": [
                "TX"
            ],
            "Carado": [
                "A",
                "T",
                "A(пасс)",
                "A(груз)",
                "T(пасс)",
                "T(груз)",
                "A",
                "T"
            ],
            "SPARK": [
                "SP110C 2",
                "sp150r 18"
            ],
            "Autobianchi": [
                "A112"
            ]
        }
    };

    var arr=[],
        obj={};
    for(var i in data.models){
      arr.push([i, _.sortBy(data.models[i],function (el){return el;})]);
    }
    arr=_.sortBy(arr,function (el){
      return el[0];
    });
    _.map(arr,function (el){return obj[el[0]]=el[1];});
     console.log(obj);

demonstração


6

Muito curto e simples!

var sortedList = {};
Object.keys(list).sort((a,b) => list[a]-list[b]).forEach((key) => {
    sortedList[key] = list[key]; });

5

Estou seguindo a solução dada por slebetman (leia-a para todos os detalhes), mas ajustada, pois seu objeto não está aninhado.

// First create the array of keys/values so that we can sort it:
var sort_array = [];
for (var key in list) {
    sort_array.push({key:key,value:list[key]});
}

// Now sort it:
sort_array.sort(function(x,y){return x.value - y.value});

// Now process that object with it:
for (var i=0;i<sort_array.length;i++) {
    var item = list[sort_array[i].key];

    // now do stuff with each item
}

4

Classificar valores sem vários for-loops (para classificar pelas chaves, altere o índice no retorno de chamada de classificação para "0")

const list = {
    "you": 100, 
    "me": 75, 
    "foo": 116, 
    "bar": 15
  };

let sorted = Object.fromEntries(
                Object.entries(list).sort( (a,b) => a[1] - b[1] )    
             ) 
console.log('Sorted object: ', sorted) 


2

Essa poderia ser uma maneira simples de lidar com isso como um objeto real ordenado. Não tenho certeza de quão lento é. também pode ser melhor com um loop while.

Object.sortByKeys = function(myObj){
  var keys = Object.keys(myObj)
  keys.sort()
  var sortedObject = Object()
  for(i in keys){
    key = keys[i]
    sortedObject[key]=myObj[key]
   }

  return sortedObject

}

E então eu encontrei essa função invertida em: http://nelsonwells.net/2011/10/swap-object-key-and-values-in-javascript/

Object.invert = function (obj) {

  var new_obj = {};

  for (var prop in obj) {
    if(obj.hasOwnProperty(prop)) {
      new_obj[obj[prop]] = prop;
    }
  }

  return new_obj;
};

assim

var list = {"you": 100, "me": 75, "foo": 116, "bar": 15};
var invertedList = Object.invert(list)
var invertedOrderedList = Object.sortByKeys(invertedList)
var orderedList = Object.invert(invertedOrderedList)

2
a = { b: 1, p: 8, c: 2, g: 1 }
Object.keys(a)
  .sort((c,b) => {
    return a[b]-a[c]
  })
  .reduce((acc, cur) => {
    let o = {}
    o[cur] = a[cur]
    acc.push(o)
    return acc
   } , [])

saída = [{p: 8}, {c: 2}, {b: 1}, {g: 1}]


2

Por precaução, alguém está procurando manter o objeto (com chaves e valores), usando a referência de código por @Markus R e o comentário de @James Moran, basta usar:

var list = {"you": 100, "me": 75, "foo": 116, "bar": 15};
var newO = {};
Object.keys(list).sort(function(a,b){return list[a]-list[b]})
                 .map(key => newO[key] = list[key]);
console.log(newO);  // {bar: 15, me: 75, you: 100, foo: 116}

2
Você está retornando uma tarefa map, forEachseria melhor #
DiegoRBaquero 18/03/19

2
let toSort = {a:2323, b: 14, c: 799} 
let sorted = Object.entries(toSort ).sort((a,b)=> a[1]-b[1]) 

Resultado:

[ [ "b", 14 ], [ "c", 799 ], [ "a", 2323 ] ]

1

muitas funções semelhantes e úteis: https://github.com/shimondoodkin/groupbyfunctions/

function sortobj(obj)
{
    var keys=Object.keys(obj);
    var kva= keys.map(function(k,i)
    {
        return [k,obj[k]];
    });
    kva.sort(function(a,b){
        if(a[1]>b[1]) return -1;if(a[1]<b[1]) return 1;
        return 0
    });
    var o={}
    kva.forEach(function(a){ o[a[0]]=a[1]})
    return o;
}

function sortobjkey(obj,key)
{
    var keys=Object.keys(obj);
    var kva= keys.map(function(k,i)
    {
        return [k,obj[k]];
    });
    kva.sort(function(a,b){
        k=key;      if(a[1][k]>b[1][k]) return -1;if(a[1][k]<b[1][k]) return 1;
        return 0
    });
    var o={}
    kva.forEach(function(a){ o[a[0]]=a[1]})
    return o;
}

1

Objeto classificado por valor (DESC)

function sortObject(list) {
  var sortable = [];
  for (var key in list) {
    sortable.push([key, list[key]]);
  }

  sortable.sort(function(a, b) {
    return (a[1] > b[1] ? -1 : (a[1] < b[1] ? 1 : 0));
  });

  var orderedList = {};
  for (var i = 0; i < sortable.length; i++) {
    orderedList[sortable[i][0]] = sortable[i][1];
  }

  return orderedList;
}

1

Aqui está mais um exemplo:

function sortObject(obj) {
  var arr = [];
  var prop;
  for (prop in obj) {
    if (obj.hasOwnProperty(prop)) {
      arr.push({
        'key': prop,
        'value': obj[prop]
      });
    }
  }
  arr.sort(function(a, b) {
    return a.value - b.value;
  });
  return arr; // returns array
}
var list = {
  car: 300,
  bike: 60,
  motorbike: 200,
  airplane: 1000,
  helicopter: 400,
  rocket: 8 * 60 * 60
};
var arr = sortObject(list);
console.log(arr);


1
    var list = {
    "you": 100,
    "me": 75,
    "foo": 116,
    "bar": 15
};
var tmpList = {};
while (Object.keys(list).length) {
    var key = Object.keys(list).reduce((a, b) => list[a] > list[b] ? a : b);
    tmpList[key] = list[key];
    delete list[key];
}
list = tmpList;
console.log(list); // { foo: 116, you: 100, me: 75, bar: 15 }

1

TypeScript

A função a seguir classifica o objeto por valor ou uma propriedade do valor. Se você não usar o TypeScript, poderá remover as informações de tipo para convertê-las em JavaScript.

/**
 * Represents an associative array of a same type.
 */
interface Dictionary<T> {
  [key: string]: T;
}

/**
 * Sorts an object (dictionary) by value or property of value and returns
 * the sorted result as a Map object to preserve the sort order.
 */
function sort<TValue>(
  obj: Dictionary<TValue>,
  valSelector: (val: TValue) => number | string,
) {
  const sortedEntries = Object.entries(obj)
    .sort((a, b) =>
      valSelector(a[1]) > valSelector(b[1]) ? 1 :
      valSelector(a[1]) < valSelector(b[1]) ? -1 : 0);
  return new Map(sortedEntries);
}

Uso

var list = {
  "one": { height: 100, weight: 15 },
  "two": { height: 75, weight: 12 },
  "three": { height: 116, weight: 9 },
  "four": { height: 15, weight: 10 },
};

var sortedMap = sort(list, val => val.height);

A ordem das chaves em um objeto JavaScript não é garantida, por isso estou classificando e retornando o resultado como um Mapobjeto que preserva a ordem de classificação.

Se você deseja convertê-lo novamente em Object, pode fazer o seguinte:

var sortedObj = {} as any;
sortedMap.forEach((v,k) => { sortedObj[k] = v });

1

input é objeto, output é objeto, usando a lib embutida lodash & js, com opção descendente ou ascendente, e não altera o objeto de entrada

por exemplo, entrada e saída

{
  "a": 1,
  "b": 4,
  "c": 0,
  "d": 2
}
{
  "b": 4,
  "d": 2,
  "a": 1,
  "c": 0
}

A implementação

const _ = require('lodash');

const o = { a: 1, b: 4, c: 0, d: 2 };


function sortByValue(object, descending = true) {
  const { max, min } = Math;
  const selector = descending ? max : min;

  const objects = [];
  const cloned = _.clone(object);

  while (!_.isEmpty(cloned)) {
    const selectedValue = selector(...Object.values(cloned));
    const [key, value] = Object.entries(cloned).find(([, value]) => value === selectedValue);

    objects.push({ [key]: value });
    delete cloned[key];
  }

  return _.merge(...objects);
}

const o2 = sortByValue(o);
console.log(JSON.stringify(o2, null, 2));

1
const arrayOfObjects = [
{name: 'test'},
{name: 'test2'}
]

const order = ['test2', 'test']

const setOrder = (arrayOfObjects, order) =>
    arrayOfObjects.sort((a, b) => {
        if (order.findIndex((i) => i === a.name) < order.findIndex((i) => i === b.name)) {
            return -1;
        }

        if (order.findIndex((i) => i === a.name) > order.findIndex((i) => i === b.name)) {
            return 1;
        }

        return 0;
    });

1

minha solução com sort:

let list = {
    "you": 100, 
    "me": 75, 
    "foo": 116, 
    "bar": 15
};

let sorted = Object.entries(list).sort((a,b) => a[1] - b[1]);

for(let element of sorted) {
    console.log(element[0]+ ": " + element[1]);
}

Formate seu código como código
Itamar Mushkin

1
<pre>
function sortObjectByVal(obj){  
var keysSorted = Object.keys(obj).sort(function(a,b){return obj[b]-obj[a]});
var newObj = {};
for(var x of keysSorted){
    newObj[x] = obj[x];
}
return newObj;

}
var list = {"you": 100, "me": 75, "foo": 116, "bar": 15};
console.log(sortObjectByVal(list));
</pre>

1
Bem-vindo ao stackoverflow. Além da resposta que você forneceu, considere fornecer uma breve explicação de por que e como isso resolve o problema.
jtate

0

Outra maneira de resolver isso: -

var res = [{"s1":5},{"s2":3},{"s3":8}].sort(function(obj1,obj2){ 
 var prop1;
 var prop2;
 for(prop in obj1) {
  prop1=prop;
 }
 for(prop in obj2) {
  prop2=prop;
 }
 //the above two for loops will iterate only once because we use it to find the key
 return obj1[prop1]-obj2[prop2];
});

// res terá a matriz de resultados


0

Obrigado e continue a responder @Nosredna

Agora que entendemos que o objeto precisa ser convertido em matriz, classifique a matriz. isso é útil para classificar a matriz (ou objeto convertido em matriz) por string:

Object {6: Object, 7: Object, 8: Object, 9: Object, 10: Object, 11: Object, 12: Object}
   6: Object
   id: "6"
   name: "PhD"
   obe_service_type_id: "2"
   __proto__: Object
   7: Object
   id: "7"
   name: "BVC (BPTC)"
   obe_service_type_id: "2"
   __proto__: Object


    //Sort options
    var sortable = [];
    for (var vehicle in options)
    sortable.push([vehicle, options[vehicle]]);
    sortable.sort(function(a, b) {
        return a[1].name < b[1].name ? -1 : 1;
    });


    //sortable => prints  
[Array[2], Array[2], Array[2], Array[2], Array[2], Array[2], Array[2]]
    0: Array[2]
    0: "11"
    1: Object
        id: "11"
        name: "AS/A2"
        obe_service_type_id: "2"
        __proto__: Object
        length: 2
        __proto__: Array[0]
    1: Array[2]
    0: "7"
    1: Object
        id: "7"
        name: "BVC (BPTC)"
        obe_service_type_id: "2"
        __proto__: Object
        length: 2

0

Tente isso. Mesmo o seu objeto não possuir a propriedade com base na qual você está tentando classificar também será tratado.

Basta chamá-lo enviando propriedade com objeto.

var sortObjectByProperty = function(property,object){

    console.time("Sorting");
    var  sortedList      = [];
         emptyProperty   = [];
         tempObject      = [];
         nullProperty    = [];
    $.each(object,function(index,entry){
        if(entry.hasOwnProperty(property)){
            var propertyValue = entry[property];
            if(propertyValue!="" && propertyValue!=null){
              sortedList.push({key:propertyValue.toLowerCase().trim(),value:entry});  
            }else{
                emptyProperty.push(entry);
           }
        }else{
            nullProperty.push(entry);
        }
    });

      sortedList.sort(function(a,b){
           return a.key < b.key ? -1 : 1;
         //return a.key < b.key?-1:1;   // Asc 
         //return a.key < b.key?1:-1;  // Desc
      });


    $.each(sortedList,function(key,entry){
        tempObject[tempObject.length] = entry.value;
     });

    if(emptyProperty.length>0){
        tempObject.concat(emptyProperty);
    }
    if(nullProperty.length>0){
        tempObject.concat(nullProperty);
    }
    console.timeEnd("Sorting");
    return tempObject;
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.