A partir desta pergunta original , como eu aplicaria uma classificação em vários campos?
Usando essa estrutura levemente adaptada, como classificaria a cidade (crescente) e o preço (decrescente)?
var homes = [
{"h_id":"3",
"city":"Dallas",
"state":"TX",
"zip":"75201",
"price":"162500"},
{"h_id":"4",
"city":"Bevery Hills",
"state":"CA",
"zip":"90210",
"price":"319250"},
{"h_id":"6",
"city":"Dallas",
"state":"TX",
"zip":"75000",
"price":"556699"},
{"h_id":"5",
"city":"New York",
"state":"NY",
"zip":"00010",
"price":"962500"}
];
Gostei do fato de ter sido dada uma resposta que forneceu uma abordagem geral. Onde pretendo usar esse código, terei que classificar datas e outras coisas. A capacidade de "aprontar" o objeto parecia útil, se não um pouco complicada.
Tentei transformar essa resposta em um bom exemplo genérico, mas não estou tendo muita sorte.
javascript
arrays
sorting
Mike
fonte
fonte
sort(["first-field", "ASC"], ["second-field", "DSC"]);
Isso é ainda mais complicado quando tento adicionar a lógica "primer" da primeira resposta para poder lidar com datas, sem distinção entre maiúsculas e minúsculas etc.Respostas:
Um método de classificação multidimensional, com base nesta resposta :
Atualização : Aqui está uma versão "otimizada". Ele faz muito mais pré-processamento e cria uma função de comparação para cada opção de classificação antecipadamente. Pode precisar de mais memória (pois armazena uma função para cada opção de classificação, mas deve ser um pouco melhor, pois não precisa determinar as configurações corretas durante a comparação. Ainda não fiz nenhum perfil.
Exemplo de uso:
DEMO
Função original:
DEMO
fonte
para uma solução simples e não genérica para o seu problema exato:
fonte
if
instrução não faz sentido.a.localeCompare(b)
na última linha para comparar as strings ... consulte os documentos #if (a.city === b.city)
? Ou seja, se as duas cidades forem iguais, compare os preços; caso contrário, compare as cidades.Você pode usar uma abordagem de classificação encadeada tomando o delta de valores até que ele atinja um valor diferente de zero.
Ou, usando es6, simplesmente:
fonte
Aqui está uma abordagem funcional simples. Especifique a ordem de classificação usando a matriz. Prefira menos para especificar a ordem decrescente.
Edit: no ES6 é ainda mais curto!
fonte
[10,100,11,9]
. Perdi alguma coisa?Eu fiz um classificador multi-recurso bastante genérico hoje. Você pode dar uma olhada no thenBy.js aqui: https://github.com/Teun/thenBy.js
Ele permite que você use o padrão Array.sort, mas com o estilo firstBy (). ThenBy (). ThenBy (). É muito menos código e complexidade do que as soluções postadas acima.
fonte
A função a seguir permitirá classificar uma matriz de objetos em uma ou várias propriedades, crescente (padrão) ou decrescente em cada propriedade, além de permitir que você escolha se deseja ou não realizar comparações que diferenciam maiúsculas de minúsculas. Por padrão, essa função executa classificações sem distinção entre maiúsculas e minúsculas.
O primeiro argumento deve ser a matriz que contém os objetos. O (s) argumento (s) subseqüente (s) deve ser uma lista separada por vírgula de seqüências de caracteres que fazem referência às diferentes propriedades do objeto a serem classificadas. O último argumento (que é opcional) é um booleano para escolher se você deve ou não classificar com distinção entre maiúsculas e minúsculas - use
true
para classificações com distinção entre maiúsculas e minúsculas.A função classificará cada propriedade / chave em ordem crescente por padrão. Se você quer uma tecla específica para classificar em ordem decrescente, em seguida, passar em vez de uma matriz neste formato:
['property_name', true]
.Aqui estão alguns exemplos de usos da função, seguidos por uma explicação (onde
homes
está uma matriz que contém os objetos):objSort(homes, 'city')
-> classificar por cidade (crescente, sensível a maiúsculas e minúsculas)objSort(homes, ['city', true])
-> classificar por cidade (decrescente, diferencia maiúsculas de minúsculas)objSort(homes, 'city', true)
-> classificar por cidade e preço (crescente, diferenciando maiúsculas de minúsculas )objSort(homes, 'city', 'price')
-> classificar por cidade e preço (ambos em ordem crescente, diferenciando maiúsculas de minúsculas)objSort(homes, 'city', ['price', true])
-> classificar por cidade (crescente) e preço (decrescente), diferenciando maiúsculas de minúsculas)E sem mais delongas, aqui está a função:
E aqui estão alguns dados de exemplo:
fonte
Este é um truque completo, mas acho que agrega valor a essa pergunta, porque é basicamente uma função de biblioteca enlatada que você pode usar imediatamente.
Se o seu código tiver acesso
lodash
ou uma biblioteca compatível com lodash como essaunderscore
, você poderá usar o_.sortBy
método O trecho abaixo é copiado diretamente da documentação do lodash .Os resultados comentados nos exemplos parecem retornar matrizes de matrizes, mas isso mostra apenas a ordem e não os resultados reais, que são uma matriz de objetos.
fonte
Aqui está outro que talvez seja mais próximo da sua ideia para a sintaxe
Demonstração: http://jsfiddle.net/Nq4dk/2/
Edit: Apenas por diversão, aqui está uma variação que leva apenas uma string do tipo sql, para que você possa fazer
sortObjects(homes, "city, price desc")
fonte
Um mais simples:
fonte
Eu gosto da abordagem de SnowBurnt, mas ela precisa de um ajuste para testar a equivalência na cidade, NÃO é uma diferença.
fonte
Aqui está uma classificação multidimensional genérica, permitindo a reversão e / ou mapeamento em cada nível.
Escrito em Texto Dactilografado. Para Javascript, confira este JSFiddle
O código
Exemplos de uso
Classificando uma matriz de pessoas por sobrenome e primeiro nome:
Classifique os códigos de idioma pelo nome , não pelo código do idioma (veja
map
) e depois pela versão descendente (vejareverse
).fonte
Uma maneira dinâmica de fazer isso com várias teclas:
Usar:
fonte
Aqui está uma versão genérica da solução do @ Snowburnt:
Isso é baseado em uma rotina de classificação que estou usando. Não testei esse código específico, pois pode haver erros, mas você entendeu. A idéia é classificar com base no primeiro campo que indica uma diferença e depois parar e passar para o próximo registro. Portanto, se você estiver classificando por três campos e o primeiro campo na comparação for suficiente para determinar a ordem de classificação dos dois registros que estão sendo classificados, retorne esse resultado e vá para o próximo registro.
Testei-o (na verdade, com uma lógica de classificação um pouco mais complexa) em 5000 registros e ele fez isso em um piscar de olhos. Se você estiver carregando mais de 1000 registros no cliente, provavelmente deverá usar a classificação e filtragem do lado do servidor.
Este código não está lidando com distinção entre maiúsculas e minúsculas, mas deixo para o leitor lidar com essa modificação trivial.
fonte
Aqui está minha solução baseada no idioma da transformação de Schwartzian , espero que você ache útil.
Aqui está um exemplo de como usá-lo:
fonte
Outra maneira
fonte
Como usar (colocar - (menos) sinal antes do campo, se você deseja classificar em um determinado campo em ordem decrescente)
Usando a função acima, você pode classificar qualquer array json com vários campos. Não é necessário alterar o corpo da função
fonte
Adaptação da resposta de @chriskelly.
A maioria das respostas ignora que o preço não será classificado adequadamente se o valor estiver na casa dos dez mil e for menor ou superior a um milhão. A razão de ser JS é classificada em ordem alfabética. Foi respondida muito bem aqui: por que o JavaScript não pode classificar "5, 10, 1" e aqui? Como classificar uma matriz de números inteiros corretamente .
Por fim, precisamos fazer alguma avaliação se o campo ou nó pelo qual estamos classificando for um número. Não estou dizendo que
parseInt()
, neste caso, é a resposta correta, os resultados classificados são mais importantes.Um violino para testar
fonte
price
no exemplo está no formato de sequência. Se você deseja que funcione corretamente com o meu exemplo, use map para converter o campo que deseja numerar primeiro o formato. ieconst correctedHomes = homes.map(h => ({...h, price: +h.price}))
Uau, existem algumas soluções complexas aqui. Tão complexo que decidi criar algo mais simples, mas também bastante poderoso. Aqui está;
E aqui está um exemplo de como você o usa.
Isso primeiro classificará pela precedência dos atributos, depois pelo valor dos atributos.
fonte
Aqui está uma maneira extensível de classificar por vários campos.
Notas
a.localeCompare(b)
é universalmente suportado e retorna -1,0,1 sea<b
,a==b
,a>b
respectivamente.||
na última linha dácity
prioridade sobreprice
.-price_order
var date_order = new Date(left.date) - new Date(right.date);
funciona como numerics porque data de matemática se transforma em milissegundos desde 1970.return city_order || -price_order || date_order;
fonte
Eu acho que essa pode ser a maneira mais fácil de fazer isso.
https://coderwall.com/p/ebqhca/javascript-sort-by-two-fields
É realmente simples e tentei com 3 pares de valores-chave diferentes e funcionou muito bem.
Aqui está um exemplo simples, veja o link para mais detalhes
fonte
Aqui está o meu para sua referência, com o exemplo:
fonte
Eu estava procurando por algo semelhante e acabei com isso:
Primeiro, temos uma ou mais funções de classificação, sempre retornando 0, 1 ou -1:
Você pode criar mais funções para cada outra propriedade na qual deseja classificar.
Então eu tenho uma função que combina essas funções de classificação em uma:
Isso pode ser usado para combinar as funções de classificação acima de uma maneira legível:
Quando uma função de classificação retorna 0, a próxima função de classificação será chamada para classificação adicional.
fonte
Apenas outra opção. Considere usar a seguinte função de utilitário:
Exemplo de uso (no seu caso):
Deve-se notar que essa função pode ser ainda mais generalizada para poder usar propriedades aninhadas como 'address.city' ou 'style.size.width' etc.
fonte
Este é um algoritmo recursivo para classificar por vários campos e ter a chance de formatar valores antes da comparação.
Se aeb forem iguais, tente apenas o próximo campo até que nenhum esteja disponível.
fonte
fonte
Aqui 'AffiliateDueDate' e 'Title' são colunas, ambas classificadas em ordem crescente.
fonte
Classificação em dois campos de data e um exemplo de campo numérico:
http://jsfiddle.net/hcWgf/57/
fonte
Usando:
Mostrar snippet de código
fonte
Que tal esta solução simples:
Baseado nesta questão, javascript classifica a matriz por vários campos (número)
fonte