Eu tenho uma matriz:
[1, 2, 3, 5, 2, 8, 9, 2]
Gostaria de saber quantos 2
s estão na matriz.
Qual é a maneira mais elegante de fazer isso em JavaScript sem fazer loop com for
loop?
javascript
Leem
fonte
fonte
const count = countItems(array, 2);
e os detalhes da implementação podem ser discutidos por dentro.[ esta resposta é um pouco datada: leia as edições ]
Diga olá aos seus amigos:
map
efilter
ereduce
eforEach
eevery
etc.(Ocasionalmente, apenas escrevo for-loops em javascript, devido à falta de escopo no nível do bloco; portanto, você precisa usar uma função como corpo do loop de qualquer maneira, se precisar capturar ou clonar seu índice ou valor de iteração. geralmente são mais eficientes, mas às vezes você precisa de um fechamento.)
A maneira mais legível:
(Poderíamos ter escrito
.filter(function(x){return x==2}).length
)A seguir, é mais eficiente em termos de espaço (O (1) em vez de O (N)), mas não tenho certeza de quanto benefício / penalidade você pode pagar em termos de tempo (não mais que um fator constante desde a sua visita) cada elemento exatamente uma vez):
(Se você precisar otimizar esse trecho de código específico, um loop for pode ser mais rápido em alguns navegadores ... você pode testar as coisas em jsperf.com.)
Você pode ser elegante e transformá-lo em uma função de protótipo:
Como isso:
Você também pode usar a técnica antiga de loop for regular (consulte outras respostas) dentro da definição de propriedade acima (novamente, isso provavelmente seria muito mais rápido).
2017 editar :
Opa, essa resposta ficou mais popular que a resposta correta. Na verdade, basta usar a resposta aceita. Embora essa resposta possa ser engraçada, os compiladores js provavelmente não otimizam (ou não podem devido à especificação) desses casos. Então você realmente deve escrever um loop for simples:
Você pode definir uma versão
.countStrictEq(...)
que use a===
noção de igualdade. A noção de igualdade pode ser importante para o que você está fazendo! (por exemplo[1,10,3,'10'].count(10)==2
, porque números como '4' == 4 em javascript ... portanto, chamá-lo.countEq
ou.countNonstrict
enfatizar que ele usa o==
operador.)Considere também usar sua própria estrutura de dados multiset (por exemplo, como a de python '
collections.Counter
') para evitar ter que fazer a contagem em primeiro lugar.Demo:
Nota: No entanto, se você ainda deseja a maneira de programação funcional (ou uma linha descartável descartável sem substituir o Array.prototype), você pode escrevê-la com mais facilidade hoje em dia como
[...].filter(x => x==2).length
. Se você se preocupa com o desempenho, observe que, embora este seja assintoticamente o mesmo desempenho que o loop for (O (N) time), ele pode exigir O (N) memória extra (em vez da memória O (1)), porque quase certamente gere uma matriz intermediária e conte os elementos dessa matriz intermediária.fonte
array.reduce(function(total,x){return x==value? : total+1 : total}, 0)
[...].reduce(function(total,x){return x==2 ? total+1 : total}, 0)
const count = (list) => list.filter((x) => x == 2).length
. Em seguida, use-o chamandocount(list)
where list é uma matriz de números. Você também pode fazerconst count = (list) => list.filter((x) => x.someProp === 'crazyValue').length
para contar instâncias de crazyValue na matriz de objetos. Observe que é uma correspondência exata para a propriedade.Atualização do ES6 para JS:
Observe que você sempre deve usar iguais a triplos:
===
para obter uma comparação correta:A seguinte função Arrow unânime (função lambda) em JS:
pode ser simplificado para este formulário conciso para uma única entrada:
onde o
return
está implícito.fonte
2017: se alguém ainda estiver interessado na pergunta, minha solução é a seguinte:
fonte
Se você estiver usando lodash ou sublinhado, o método _.countBy fornecerá um objeto de totais agregados codificados por cada valor na matriz. Você pode transformar isso em uma linha só se precisar contar apenas um valor:
Isso também funciona bem em matrizes de números. O one-liner para o seu exemplo seria:
fonte
A maneira mais estranha de pensar em fazer isso é:
Onde:
Minha sugestão, use um tempo ou para loop ;-)
fonte
Não usar um laço normalmente significa entregar o processo ao longo de algum método que não usar um loop.
Aqui está uma maneira do nosso codificador odiador de loop satisfazer o seu ódio, a um preço:
Você também pode chamar indexOf repetidamente, se estiver disponível como método de matriz, e mover o ponteiro da pesquisa a cada vez.
Isso não cria uma nova matriz, e o loop é mais rápido que um forEach ou filtro.
Pode fazer a diferença se você tiver um milhão de membros para olhar.
fonte
String(a).match(/2/g).length + 1
- embora tenha cuidado com isso ou sua implementação não funcionará bem com dois dígitos.A maioria das soluções postadas usando funções de matriz, como filtro, estão incompletas porque não são parametrizadas.
Aqui está uma solução com a qual o elemento a ser contado pode ser definido em tempo de execução.
A vantagem dessa abordagem é que poderia facilmente mudar a função para contar, por exemplo, o número de elementos maiores que X.
Você também pode declarar a função de redução embutida
fonte
var elementToFind=2; ... function (elementToFind, total, number){ return total += number==elementToFind; }.bind(this, elementToFind) ...
é mais difícil de ler e não oferece vantagem sobre apenas... (acc, x) => acc += number == 2...
. Eu gosto do seu uso em+=
vez de noacc + (number == 2)
entanto. Parece uma sintaxe injustificada HACK.Realmente, por que você precisaria
map
oufilter
para isso?reduce
nasceu "para este tipo de operações:[1, 2, 3, 5, 2, 8, 9, 2].reduce( (count,2)=>count+(item==val), 0);
é isso aí! (se
item==val
em cada iteração, 1 será adicionado ao acumuladorcount
, conformetrue
será resolvido em1
).Como uma função:
Ou vá em frente e estenda suas matrizes:
fonte
É melhor envolvê-lo em função:
fonte
Aqui está uma maneira do ES2017 + de obter as contagens para todos os itens da matriz em O (N):
Você também pode, opcionalmente, classificar a saída:
console.log (countsSorted) para sua matriz de exemplo:
fonte
Eu acredito que o que você está procurando é uma abordagem funcional
elem === 'a' é a condição, substitua-a por sua.
fonte
count = arr.filter(elem => elem === 'a').length
oucount = arr.filter(elem => {return elem === 'a'}).length
Eu sou um fã iniciante da função de redução do array js.
De fato, se você realmente deseja ter uma fantasia, pode criar uma função de contagem no protótipo Array. Então você pode reutilizá-lo.
Então faça
fonte
Solução por recursão
fonte
filter
,reduce
ou uma simplesforLoop
e também mais cara quando se olha para o desempenho, mas ainda é uma ótima maneira de fazê-lo com recursão. Minha única mudança é: acho que seria melhor criar uma função e adicionar um filtro dentro dela para copiar a matriz e evitar uma mutação da matriz original, depois use a recursiva como uma função interna.Eu faria algo assim:
fonte
Crie um novo método para a classe Array no arquivo de nível principal e use-o em todo o seu projeto.
Use isso em qualquer lugar do seu projeto -
fonte
Aqui está um liner em javascript.
(v === 2)
na matriz, retornando uma matriz de uns e zeros.O resultado é
3
.fonte
Dependendo de como você deseja executá-lo:
fonte
Você pode usar a propriedade length na matriz JavaScript:
fonte