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
};
Steerpike
fonte
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]
})
Nosredna
fonte
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

Markus R
fonte
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/

inorganik
fonte
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.

Stano
fonte
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]]
kiding
fonte
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!

Jason J. Nathan
fonte
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.

NickFitz
fonte
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

Alireza
fonte
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}
Vasil Nikolov
fonte
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
julianljk
fonte
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

Roman Yudin
fonte
6

Muito curto e simples!

var sortedList = {};
Object.keys(list).sort((a,b) => list[a]-list[b]).forEach((key) => {
    sortedList[key] = list[key]; });
Maryam Koulaei
fonte
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
}
bonna
fonte
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) 

dino4udo
fonte
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)
Carson Wright
fonte
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}]

Kiran Debnath
fonte
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}
esneyderp
fonte
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 ] ]
Remi Prasanna
fonte
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;
}
Shimon Doodkin
fonte
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;
}
victorhazbun
fonte
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);

Mahendra Kulkarni
fonte
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 }
Milad Aslani
fonte
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 });
orad
fonte
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));
James T.
fonte
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;
    });
Oleg
fonte
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]);
}
Ivan Bozveliev
fonte
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>
Chirag Modi
fonte
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

vivek_nk
fonte
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
Fúria
fonte
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;
}
Vali Shah
fonte