259 votes

Compter les occurrences des éléments d'un tableau Javascript

En Javascript, j'essaie de prendre un tableau initial de valeurs numériques et de compter les éléments qu'il contient. Idéalement, le résultat serait deux nouveaux tableaux, le premier spécifiant chaque élément unique, et le second contenant le nombre de fois que chaque élément apparaît. Cependant, je suis ouvert à toute suggestion concernant le format de la sortie.

Par exemple, si le tableau initial était :

5, 5, 5, 2, 2, 2, 2, 2, 9, 4

Ensuite, deux nouveaux tableaux seront créés. Le premier contiendrait le nom de chaque élément unique :

5, 2, 9, 4

Le second contiendrait le nombre de fois que cet élément apparaît dans le tableau initial :

3, 5, 1, 1

Comme le nombre 5 apparaît trois fois dans le tableau initial, le nombre 2 apparaît cinq fois et le 9 et le 4 apparaissent tous deux une fois.

J'ai beaucoup cherché une solution, mais rien ne semble fonctionner, et tout ce que j'ai essayé moi-même s'est avéré ridiculement complexe. Toute aide serait la bienvenue !

Merci :)

10 votes

Si tout ce dont vous aviez besoin était de voir si une valeur n'apparaît qu'une seule fois (au lieu de deux ou plusieurs fois), vous pourriez utiliser la méthode suivante if (arr.indexOf(value) == arr.lastIndexOf(value))

1 votes

Nous pouvons utiliser ramda.js pour y parvenir de manière simple. const ary = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4]; R.countBy(r=> r)(ary)

0 votes

arr.filter(x => x===5).length rendrait 3 pour indiquer qu'il y a "3" cinq dans le tableau.

265voto

typeof Points 2001

Vous pouvez utiliser un objet pour contenir les résultats :

var arr = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4];
var counts = {};

for(var i = 0; i< arr.length; i++) {
    var num = arr[i];
    counts[num] = counts[num] ? counts[num]+1 : 1;
}

Donc, maintenant votre objet compte peut vous dire quel est le compte pour un nombre particulier :

console.log(counts[5]); // logs '3'

Si vous voulez obtenir un tableau de membres, utilisez simplement la fonction keys() fonctions

keys(counts); // returns ["5", "2", "9", "4"]

3 votes

Il convient de souligner que Object.keys() n'est supportée que dans IE9+, FF4+, SF5+, CH6+ mais Opera ne la supporte pas. Je pense que le plus gros obstacle ici est IE9+. .

22 votes

De même, j'aime aussi counts[num] = (counts[num] || 0) + 1 . De cette façon, vous n'avez qu'à écrire counts[num] deux fois au lieu de trois sur cette ligne-là.

2 votes

C'est une bonne réponse. Il est facile d'abstraire cela en une fonction qui accepte un tableau et renvoie un objet 'counts'.

113voto

adamse Points 4458
var a = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4].reduce(function (acc, curr) {
  if (typeof acc[curr] == 'undefined') {
    acc[curr] = 1;
  } else {
    acc[curr] += 1;
  }

  return acc;
}, {});

// a == {2: 5, 4: 1, 5: 3, 9: 1}

49 votes

acc[curr] ? acc[curr]++ : acc[curr] = 1;

0 votes

Merci, très bonne solution ;) ... et pour obtenir les tableaux "key" et "value" : const keys = Object.keys(a); const values = Object.values(a);

0 votes

Une main courte : acc[curr] = (acc[curr] || 0) + 1 au lieu d'utiliser if/else . Vous pouvez vérifier la réponse ci-dessous

107voto

Šime Vidas Points 59994

Voilà :

function foo(arr) {
    var a = [], b = [], prev;

    arr.sort();
    for ( var i = 0; i < arr.length; i++ ) {
        if ( arr[i] !== prev ) {
            a.push(arr[i]);
            b.push(1);
        } else {
            b[b.length-1]++;
        }
        prev = arr[i];
    }

    return [a, b];
}

Démonstration en direct : http://jsfiddle.net/simevidas/bnACW/

30 votes

A pour effet secondaire de trier le tableau (les effets secondaires sont mauvais), le tri est également O(N log(N)) et le gain d'élégance n'en vaut pas la peine

0 votes

En l'absence d'une belle primitive de haut niveau provenant d'une bibliothèque tierce, j'implémenterais normalement cette fonction comme la fonction reduce réponse. J'étais sur le point de soumettre une telle réponse avant de voir qu'elle existait déjà. Néanmoins, la counts[num] = counts[num] ? counts[num]+1 : 1 fonctionne également (équivalent à la réponse if(!result[a[i]])result[a[i]]=0 qui est plus élégante mais moins facile à lire) ; ces réponses peuvent être modifiées pour utiliser une version plus "sympa" de la boucle for, peut-être une boucle for tierce, mais j'ai en quelque sorte ignoré cela puisque les boucles for standard basées sur l'index sont malheureusement la valeur par défaut.

0 votes

Pour les petits tableaux, le tri sur place peut être plus rapide que la création d'un tableau associatif.

61voto

mu is too short Points 205090

N'utilisez pas deux tableaux pour le résultat, utilisez un objet :

a      = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4];
result = { };
for(i = 0; i < a.length; ++i) {
    if(!result[a[i]])
        result[a[i]] = 0;
    ++result[a[i]];
}

Puis result aura l'air :

{
    2: 5,
    4: 1,
    5: 3,
    9: 1
}

8voto

snrobot Points 331

Si vous utilisez l'underscore, vous pouvez suivre la voie fonctionnelle.

a = ['foo', 'foo', 'bar'];

var results = _.reduce(a,function(counts,key){ counts[key]++; return counts },
                  _.object( _.map( _.uniq(a), function(key) { return [key, 0] })))

donc votre premier tableau est

_.keys(results)

et le deuxième tableau est

_.values(results)

la plupart de ces fonctions seront remplacées par des fonctions javascript natives si elles sont disponibles.

démo : http://jsfiddle.net/dAaUU/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X