자바스크립트로 숫자 세기

WBOY
풀어 주다: 2024-08-08 07:17:32
원래의
489명이 탐색했습니다.

Counting things in Javascript

Si vous souhaitez compter le nombre d'éléments d'une variété spécifique dans un tableau, vous pouvez filtrer ce tableau et vérifier la longueur du résultat.

const letters = ['a','b','b','c','c','c']; const numberOfC = letters.filter(letter => letter === 'c').length; console.log(numberOfC); // 3
로그인 후 복사

Cela a une complexité temporelle de O(n), qui est l'idéal théorique pour ce type de problème. Il utilise de la mémoire supplémentaire pour contenir un deuxième tableau, mais pour ne compter qu'une seule variété d'éléments, il s'agit d'une approche courante et suffisamment efficace dans la plupart des situations. Cependant, ce n'est pas une approche efficace si vous souhaitez compter toutes les variétés d'éléments du tableau.

Le problème avec le filtre

Si nous voulions compter non seulement le « c » mais aussi chaque lettre du tableau, l'application naïve de cette technique ressemblerait à ceci :

const letters = ['a','b','b','c','c','c']; letters.forEach((letter, _, arr) => { const count = arr.filter(otherLetter => otherLetter === letter).length; console.log(letter, count); });
로그인 후 복사

Cela produit le résultat suivant :

a 1 b 2 b 2 c 3 c 3 c 3
로그인 후 복사

Les décomptes sont corrects, mais il y a une redondance, qui peut être corrigée en utilisant d'abord un Set.

const letters = ['a','b','b','c','c','c']; const uniqueLetters = new Set(letters); for(const letter of uniqueLetters){ const count = letters.filter(otherLetter => otherLetter === letter).length; console.log(letter, count); };
로그인 후 복사

La sortie résultante n'a aucun doublon :

a 1 b 2 c 3
로그인 후 복사

Cependant, il a une complexité temporelle de O(n^2), car chaque filtre parcourt l'ensemble du tableau, et il doit le faire pour chaque lettre unique.

Une approche plus efficace

Il est possible d'effectuer ce décompte avec une complexité temporelle O(n). Le principe général est de parcourir le tableau une seule fois. Pour chaque élément rencontré, vérifiez si vous disposez déjà d’un décompte pour cet élément. Si vous le faites, incrémentez-le de 1. Si vous ne le faites pas, ajoutez un nombre pour cet élément avec une valeur définie sur 1.

Javascript dispose de deux mécanismes différents adaptés au stockage des décomptes. Nous pouvons utiliser des objets ou des cartes. Notez qu'il s'agit d'une référence à la structure de données Map et non à la méthode map() des tableaux. Utiliser une carte est plus efficace, mais utiliser des objets pour cela est encore assez courant, nous allons donc voir comment compter avec les deux.

Compter avec une carte

const letters = ['a','b','b','c','c','c']; const counts = new Map(); // Creates an empty Map letters.forEach(letter => { if(counts.has(letter)) {//Determine if the letter already has a count counts.set(letter, counts.get(letter) + 1);//Increment existing count } else counts.set(letter, 1);//Set new count to 1 }); console.log(counts); //Map(3) { 'a' => 1, 'b' => 2, 'c' => 3 }
로그인 후 복사

Le has() vérifie si la valeur est déjà dans la carte. Le set() stocke une valeur dans la carte, soit en créant une nouvelle valeur, soit en écrasant une valeur existante. Le get() obtient la valeur actuelle. Notez que has(), set() et get() ont une complexité temporelle O(1), car un hachage est utilisé en interne.

Si nous voulions extraire plus tard le nombre de lettres spécifiques, nous pourrions faire quelque chose comme :

console.log(counts.get('c'));//3
로그인 후 복사

Compter avec un objet

Bien que compter avec des objets soit plus lent, la différence de performances peut ne pas être perceptible si vous ne comptez pas une énorme quantité d'objets. Les objets sont également mieux pris en charge par le navigateur que Maps, bien que cette différence soit devenue presque sans conséquence à ce stade. Selon caniuse.com, Map est pris en charge dans 96,28 % des navigateurs au moment d'écrire ces lignes. Les objets font partie intégrante du langage Javascript et devraient être pris en charge à 100 % par le navigateur, mais caniuse.com n'a pas de liste pour cela. La principale raison pour apprendre à utiliser des objets pour les décomptes est qu’il existe de nombreux anciens codes utilisant cette technique. Certaines personnes qui ont appris de l'ancien code écrivent également du nouveau code en utilisant cette approche.

const letters = ['a','b','b','c','c','c']; const counts = {};//Create empty object for holding counts letters.forEach(letter => { if(letter in counts) {//Check if the count exists counts[letter]++;//Increment the count } else counts[letter] = 1;//Set new count to 1 }); console.log(counts);//{ a: 1, b: 2, c: 3 }
로그인 후 복사

Ce code suit la même structure que le code utilisant une Map. Les différences résident dans la syntaxe des cartes et des objets. Le mot clé "in" est utilisé pour tester si l'objet possède une clé portant ce nom. La syntaxe entre crochets est utilisée à la fois pour obtenir et définir les valeurs. Notez que tester l'appartenance, définir et obtenir des valeurs à partir d'un objet sont des opérations de complexité temporelle O(1), car les objets utilisent en interne un hachage pour les clés.

Le problème du comptage des objets

Si les choses que vous comptez sont des objets, des précautions supplémentaires sont nécessaires. Les cartes sont capables de stocker des objets sous forme de clés et préservent le type, mais cela crée un problème de comparaison d'égalité si vous avez un objet totalement différent qui a exactement les mêmes clés et valeurs.

const m = new Map(); m.set({name: "John"}, 5); console.log(m.has({name: "John"}));//false
로그인 후 복사

Ce code renvoie "false", car les deux objets n'ont pas d'égalité référentielle. Les deux objets sont identiques en termes de clés et de valeurs, mais ce ne sont pas exactement le même objet.

const m = new Map(); const obj = {name: "John"} m.set(obj, 5); console.log(m.has(obj));//true
로그인 후 복사

Cette version du code renvoie "vrai", car la valeur définie est exactement le même objet dont l'adhésion est testée.

Le résultat d'essayer de compter les objets avec Maps dans la plupart des cas est que tous les objets finiront avec un compte de 1, car chaque has() renvoie false.

L'utilisation d'objets pour compter des objets pose un problème connexe mais légèrement différent. Les clés d'objet sont automatiquement contraintes à une chaîne(Sauf lorsqu'il s'agit de symboles). Si vous essayez d'utiliser un objet comme clé d'un autre objet, ce type de coercition crée une clé égale à "[object Object]".

const obj = {name: "John"} const count = {}; count[obj] = 5; console.log(count);// { '[object Object]': 5 }
로그인 후 복사

The result of trying to count objects using objects is you will end up with an object that has "[object Object]" as the key, and the value will be the total number of all the things that were counted. There won't be any individual counts, because every item is treated as "[object Object]".

How to count objects

It is not common that you would need to count objects. If the need arises, the solution depends on whether or not the objects have a unique property that is guaranteed to be unique. For example, objects that have an id number could be counted by counting the id number occurrences instead of counting occurrences of the whole object.

const employees = [ {id: 1, name: "John"}, {id: 1, name: "John"}, {id: 2, name: "Mary"}, {id: 2, name: "Mary"}, {id: 2, name: "Mary"}, ] const counts = new Map(); employees.forEach(employee => { if(counts.has(employee.id)) { counts.set(employee.id, counts.get(employee.id) + 1); } else counts.set(employee.id, 1); }); console.log(counts);//Map(2) { 1 => 2, 2 => 3 }
로그인 후 복사

This only gives counts with ids and an extra lookup would be needed to associate the counts with names, but we can fix that with a bit more code:

const countsWithNames = []; for(const count of counts) { const employee = employees.find((employee) => employee.id === count[0]); countsWithNames.push({employee, count: count[1]}); } console.log(countsWithNames);
로그인 후 복사

The resulting output is:

[ { employee: { id: 1, name: 'John' }, count: 2 }, { employee: { id: 2, name: 'Mary' }, count: 3 } ]
로그인 후 복사

If there isn't anything like an id that guarantees uniqueness, the only remaining practical option would be to first convert the object to JSON.

const people = [ {name: "John Doe", age: 25}, {name: "John Doe", age: 25}, {name: "Mary Jane", age: 24}, {name: "Mary Jane", age: 24}, {name: "Mary Jane", age: 24} ] const counts = new Map(); people.forEach(person => { const personString = JSON.stringify(person); if(counts.has(personString)) { counts.set(personString, counts.get(personString) + 1); } else counts.set(personString, 1); }); console.log(counts);
로그인 후 복사

The resulting output is:

Map(2) { '{"name":"John Doe","age":25}' => 2, '{"name":"Mary Jane","age":24}' => 3 }
로그인 후 복사

Note that there are limitations to this approach. For example, objects with circular references cannot be stringified using JSON.stringify().

Counting non-array items

Both the techniques for counting with Maps and for counting with objects can be used to count anything, as long as you can find a way to iterate through the items. Some types of data can be converted to an array, for example, strings can be split, and keys of objects can be accessed as an array via Object.keys().

There are also some iterables that don't need to be converted into an array. For example, it's possible to iterate through the characters of a string by using an index. The same principle can be used in array-like structures like HTML Collections.

위 내용은 자바스크립트로 숫자 세기의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!