Em Javascript, estou tentando pegar uma matriz inicial de valores numéricos e contar os elementos dentro dela. Idealmente, o resultado seria duas novas matrizes, a primeira especificando cada elemento exclusivo e a segunda contendo o número de vezes que cada elemento ocorre. No entanto, estou aberto a sugestões sobre o formato da saída.
Por exemplo, se a matriz inicial fosse:
5, 5, 5, 2, 2, 2, 2, 2, 9, 4
Em seguida, duas novas matrizes seriam criadas. O primeiro conteria o nome de cada elemento exclusivo:
5, 2, 9, 4
O segundo conteria o número de vezes que esse elemento ocorreu na matriz inicial:
3, 5, 1, 1
Como o número 5 ocorre três vezes na matriz inicial, o número 2 ocorre cinco vezes e 9 e 4 aparecem uma vez.
Eu procurei muito por uma solução, mas nada parece funcionar, e tudo o que eu tentei acabou sendo ridiculamente complexo. Qualquer ajuda seria apreciada!
Obrigado :)
fonte
if (arr.indexOf(value) == arr.lastIndexOf(value))
ramda.js
para conseguir isso da maneira mais fácil.const ary = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4]; R.countBy(r=> r)(ary)
arr.filter(x => x===5).length
retornaria3
para indicar que há '3' cinco na matriz.Respostas:
Aqui está:
Demonstração ao vivo: http://jsfiddle.net/simevidas/bnACW/
fonte
O(N log(N))
ea elegância ganho não vale a penareduce
resposta. Eu estava prestes a enviar uma resposta antes de ver que ela já existia. No entanto, acounts[num] = counts[num] ? counts[num]+1 : 1
resposta também funciona (equivalente àif(!result[a[i]])result[a[i]]=0
resposta, que é mais elegante, mas menos fácil de ler); essas respostas podem ser modificadas para usar uma versão "mais agradável" do loop for, talvez um loop for de terceiros, mas eu meio que ignorei isso, já que os loops for baseados em índice padrão são, infelizmente, o padrão.Você pode usar um objeto para armazenar os resultados:
Portanto, agora seu objeto de contagem pode lhe dizer qual é a contagem para um número específico:
Se você deseja obter uma matriz de membros, basta usar as
keys()
funçõesfonte
Object.keys()
função é suportada apenas no IE9 +, FF4 +, SF5 +, CH6 +, mas o Opera não a suporta. Eu acho que a maior rolha de show aqui é o IE9 + .counts[num] = (counts[num] || 0) + 1
. Dessa forma, você só precisa escrevercounts[num]
duas vezes em vez de três vezes nessa linha.[5, "5"]
dirá simplesmente que você tem"5"
duas vezes. Ou contar instâncias de alguns objetos diferentes apenas indica que há muitos[object Object]
. Etc. etc.fonte
acc[curr] ? acc[curr]++ : acc[curr] = 1;
const keys = Object.keys(a);
const values = Object.values(a);
Se você estiver usando sublinhado ou lodash, é a coisa mais simples a fazer:
De tal modo que:
Conforme indicado por outras pessoas, você pode executar as funções
_.keys()
e_.values()
no resultado para obter apenas os números exclusivos e suas ocorrências, respectivamente. Mas, na minha experiência, o objeto original é muito mais fácil de lidar.fonte
Não use duas matrizes para o resultado, use um objeto:
Então
result
será parecido com:fonte
Que tal uma opção ECMAScript2015.
Este exemplo passa a matriz de entrada para o
Set
construtor, criando uma coleção de valores exclusivos . A sintaxe de dispersão expande esses valores em uma nova matriz, para que possamos chamarmap
e traduzir isso em uma matriz bidimensional de[value, count]
pares - ou seja, a seguinte estrutura:A nova matriz é então passada para o
Map
construtor, resultando em um objeto iterável :O melhor de um
Map
objeto é que ele preserva tipos de dados - ou sejaaCount.get(5)
, retornará,3
masaCount.get("5")
retornaráundefined
. Ele também permite que qualquer valor / tipo atue como uma chave, o que significa que esta solução também funcionará com uma matriz de objetos.Mostrar snippet de código
fonte
Set
usa referências de objeto para exclusividade e não oferece API para comparação de objetos "semelhantes" . Se você deseja usar essa abordagem para essa tarefa, precisará de alguma função de redução intermediária que garanta uma matriz de instâncias exclusivas. Não é o mais eficiente, mas reuni um exemplo rápido aqui .Eu acho que esta é a maneira mais simples de como contar ocorrências com o mesmo valor na matriz.
fonte
a.filter(value => !value).length
com a nova sintaxe jsSolução ES6 de uma linha. Tantas respostas usando o objeto como um mapa, mas não vejo ninguém usando um mapa real
Use
map.keys()
para obter elementos exclusivosUse
map.values()
para obter as ocorrênciasUse
map.entries()
para obter os pares [elemento, frequência]fonte
fonte
Se você prefere um único revestimento.
arr.reduce(function(countMap, word) {countMap[word] = ++countMap[word] || 1;return countMap}, {});
Editar (12/06/2015) : a explicação de dentro para fora. countMap é um mapa que mapeia uma palavra com sua frequência, e podemos ver a função anônima. O que reduz é aplicar a função com argumentos como todos os elementos da matriz e countMap sendo passados como o valor de retorno da última chamada de função. O último parâmetro ({}) é o valor padrão de countMap para a primeira chamada de função.
fonte
;
,{
e}
. ... ESTÁ BEM. Penso que, com essa definição de uma linha, podemos escrever o Jogo da Vida de Conway como um "delineador".A versão ES6 deve ser muito mais simplificada (outra solução de uma linha)
Um mapa em vez de um objeto simples, ajudando-nos a distinguir diferentes tipos de elementos, ou então todas as contagens são baseadas em cadeias
fonte
Se você estiver usando sublinhado, poderá seguir a rota funcional
então sua primeira matriz é
e a segunda matriz é
a maior parte disso será padronizada para funções JavaScript nativas, se estiverem disponíveis
demo: http://jsfiddle.net/dAaUU/
fonte
Com base nas respostas de @adamse e @pmandell (que eu votei), no ES6, você pode fazer isso em uma linha :
||
para reduzir o tamanho do código e torná-lo mais legível.Pode ser usado para contar caracteres :
fonte
|| 0
:(r,k)=>{r[k]=(r[k]||0)+1;return r}
Aqui está apenas algo leve e fácil para os olhos ...
Edit: E desde que você deseja todas as ocorrências ...
fonte
Então, aqui está como eu faria isso com alguns dos mais recentes recursos javascript:
Primeiro, reduza a matriz para uma
Map
das contagens:Usando a
Map
, sua matriz inicial pode conter qualquer tipo de objeto e as contagens estarão corretas. Sem aMap
, alguns tipos de objetos fornecem contagens estranhas. Consulte osMap
documentos para obter mais informações sobre as diferenças.Isso também pode ser feito com um objeto se todos os seus valores forem símbolos, números ou seqüências de caracteres:
Ou um pouco mais sofisticado de uma maneira funcional, sem mutação, usando a sintaxe da desestruturação e da propagação do objeto:
Nesse ponto, você pode usar o
Map
objeto ou para suas contagens (e o mapa é diretamente iterável, diferente de um objeto), ou convertê-lo em duas matrizes.Para o
Map
:Ou para o objeto:
fonte
fonte
Map
, pois isso evitará a transmissão tipográfica que o uso de um número como chave de objeto (conversão como string) faz.const answer = array.reduce((a, e) => a.set(e, (a.get(e) || 0) + 1), new Map())
.Você pode obteranswer.keys()
as chaves eanswer.values()
os valores como matrizes.[...answer]
fornecerá uma grande matriz com todas as chaves / valores como matrizes 2D.Solução ES6 com redução (fixa):
fonte
Edit 2020 : esta é uma resposta bastante antiga (nove anos). Estender o nativo
prototype
sempre gerará discussão . Embora eu ache que o programador é livre para escolher seu próprio estilo de programação, aqui está uma abordagem (mais moderna) do problema sem estenderArray.prototype
:A resposta antiga (2011): você poderia estender
Array.prototype
, assim:Mostrar snippet de código
fonte
Minha solução com ramda:
Link para REPL.
fonte
Solução usando um mapa com O (n) complexidade de tempo.
Demonstração: http://jsfiddle.net/simevidas/bnACW/
fonte
Existe uma maneira muito melhor e fácil de fazer isso usando
ramda.js
. Exemplo de código aquiconst ary = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4]; R.countBy(r=> r)(ary)
A documentação countBy está na documentaçãofonte
Usando o MAP, você pode ter 2 matrizes na saída: uma contendo as ocorrências e a outra contendo o número de ocorrências.
fonte
Confira o código abaixo.
fonte
Tente o seguinte:
fonte
Eu estava resolvendo um problema semelhante nas codewars e desenvolvi a seguinte solução que funcionou para mim.
Isso fornece a contagem mais alta de um número inteiro em uma matriz e também o próprio número inteiro. Eu acho que também pode ser aplicado ao array de strings.
Para classificar corretamente as cordas, remova o
function(a, b){return a-b}
de dentro dasort()
partefonte
Aqui está uma maneira de contar ocorrências dentro de uma matriz de objetos. Ele também coloca o conteúdo da primeira matriz dentro de uma nova matriz para classificar os valores para que a ordem na matriz original não seja interrompida. Em seguida, uma função recursiva é usada para percorrer cada elemento e contar a propriedade de quantidade de cada objeto dentro da matriz.
fonte
fonte
fonte
Esta pergunta tem mais de 8 anos e muitas respostas não levam realmente o ES6 e suas inúmeras vantagens em consideração.
Talvez seja ainda mais importante pensar nas consequências de nosso código para gerenciamento de coleta / memória de lixo sempre que criamos matrizes adicionais, fazemos cópias duplas ou triplas de matrizes ou mesmo convertemos matrizes em objetos. Essas são observações triviais para pequenas aplicações, mas se a escala é um objetivo de longo prazo, pense nelas minuciosamente.
Se você só precisa de um "contador" para tipos de dados específicos e o ponto de partida é uma matriz (suponho que você queira uma lista ordenada e tire proveito das muitas propriedades e métodos que as matrizes oferecem), basta simplesmente percorrer a matriz1 e preencher array2 com os valores e o número de ocorrências para esses valores encontrados no array1.
Tão simples como isso.
Exemplo de classe simples SimpleCounter (ES6) para Programação Orientada a Objetos e Design Orientado a Objetos
fonte
finalList
não tem motivo para ser uma matriz e isso não tem vantagens em fazê-lo corretamente.Aqui está um método clássico da velha escola para contar matrizes.
Você pode classificá-lo primeiro se desejar um resultado alfabético, mas se desejar preservar a ordem em que os dados foram inseridos, tente fazer isso. Os loops aninhados podem ser um pouco mais lentos que alguns dos outros métodos nesta página.
fonte