web-dev-qa-db-fra.com

Rechercher de manière idiomatique le nombre d'occurrences d'une valeur donnée dans un tableau

J'ai un tableau avec des valeurs répétitives. J'aimerais trouver le nombre d'occurrences pour une valeur donnée. 

Par exemple, si j'ai un tableau défini comme suit: var dataset = [2,2,4,2,6,4,7,8];, je souhaite rechercher le nombre d'occurrences d'une certaine valeur dans le tableau. C'est-à-dire que le programme devrait indiquer que si j'ai 3 occurrences de la valeur 2, 1 occurrence de la valeur 6, etc.

Quelle est la manière la plus idiomatique/élégante de le faire?

35
Shrey Gupta

reduce est plus approprié ici que filter car il ne crée pas de tableau temporaire juste pour compter.

var dataset = [2,2,4,2,6,4,7,8];
var search = 2;

var count = dataset.reduce(function(n, val) {
    return n + (val === search);
}, 0);

console.log(count);

Notez qu'il est facile d'étendre cela à l'aide d'un prédicat correspondant personnalisé, par exemple, à compter les objets ayant une propriété spécifique:

people = [
    {name: 'Mary', gender: 'girl'},
    {name: 'Paul', gender: 'boy'},
    {name: 'John', gender: 'boy'},
    {name: 'Lisa', gender: 'girl'},
    {name: 'Bill', gender: 'boy'},
    {name: 'Maklatura', gender: 'girl'}
]

var numBoys = people.reduce(function (n, person) {
    return n + (person.gender == 'boy');
}, 0);

console.log(numBoys);

Compter tous les éléments, c’est-à-dire créer un objet tel que {x:count of xs} est compliqué en javascript, car les clés d’objet ne peuvent être que des chaînes et vous ne pouvez donc pas compter de manière fiable un tableau avec des types mélangés. Néanmoins, la solution simple suivante fonctionnera bien dans la plupart des cas:

count = function (ary, classifier) {
    classifier = classifier || String;
    return ary.reduce(function (counter, item) {
        var p = classifier(item);
        counter[p] = counter.hasOwnProperty(p) ? counter[p] + 1 : 1;
        return counter;
    }, {})
};

people = [
    {name: 'Mary', gender: 'girl'},
    {name: 'Paul', gender: 'boy'},
    {name: 'John', gender: 'boy'},
    {name: 'Lisa', gender: 'girl'},
    {name: 'Bill', gender: 'boy'},
    {name: 'Maklatura', gender: 'girl'}
];

// If you don't provide a `classifier` this simply counts different elements:

cc = count([1, 2, 2, 2, 3, 1]);
console.log(cc);

// With a `classifier` you can group elements by specific property:

countByGender = count(people, function (item) {
    return item.gender
});
console.log(countByGender);

Mise à jour 2017

Dans ES6, vous utilisez l'objet Map pour compter de manière fiable les objets de types arbitraires:

class Counter extends Map {
    constructor(iter, key=null) {
        super();
        this.key = key || (x => x);
        for (let x of iter) {
            this.add(x);
        }
    }
    add(x) {
      x = this.key(x);
      this.set(x, (this.get(x) || 0) + 1);
    }
}

// again, with no classifier just count distinct elements

results = new Counter([1, 2, 3, 1, 2, 3, 1, 2, 2]);
for (let [number, times] of results.entries())
    console.log('%s occurs %s times', number, times);


// counting objects

people = [
    {name: 'Mary', gender: 'girl'},
    {name: 'John', gender: 'boy'},
    {name: 'Lisa', gender: 'girl'},
    {name: 'Bill', gender: 'boy'},
    {name: 'Maklatura', gender: 'girl'}
];


chessChampions = {
    2010: people[0],
    2012: people[0],
    2013: people[2],
    2014: people[0],
    2015: people[2],
};

results = new Counter(Object.values(chessChampions));
for (let [person, times] of results.entries())
    console.log('%s won %s times', person.name, times);

// you can also provide a classifier as in the above

byGender = new Counter(people, x => x.gender);
for (let g of ['boy', 'girl'])
   console.log("there are %s %ss", byGender.get(g), g);

74
georg

Navigateurs plus récents uniquement en raison de l'utilisation de Array.filter

var dataset = [2,2,4,2,6,4,7,8];
var search = 2;
var occurrences = dataset.filter(function(val) {
    return val === search;
}).length;
console.log(occurrences); // 3
11
goat
array.filter(c => c === searchvalue).length;
9
Julian Wagner

Voici un moyen de montrerTOUTcompte à la fois:

var dataset = [2, 2, 4, 2, 6, 4, 7, 8];
var counts = {}, i, value;
for (i = 0; i < dataset.length; i++) {
    value = dataset[i];
    if (typeof counts[value] === "undefined") {
        counts[value] = 1;
    } else {
        counts[value]++;
    }
}
console.log(counts);
// Object {
//    2: 3,
//    4: 2,
//    6: 1,
//    7: 1,
//    8: 1
//}
8
Salman A

En utilisant une boucle normale, vous pouvez trouver les occurrences de manière cohérente et fiable:

const dataset = [2,2,4,2,6,4,7,8];

function getNumMatches(array, valToFind) {
    let numMatches = 0;
    for (let i = 0, j = array.length; i < j; i += 1) {
        if (array[i] === valToFind) {
            numMatches += 1;
        }
    }
    return numMatches;
}

alert(getNumMatches(dataset, 2)); // should alert 3

DEMO:https://jsfiddle.net/a7q9k4uu/

Pour la rendre plus générique, la fonction pourrait accepter une fonction de prédicat avec une logique personnalisée (renvoyer truefalse) qui déterminerait le nombre final. Par exemple:

const dataset = [2,2,4,2,6,4,7,8];

function getNumMatches(array, predicate) {
    let numMatches = 0;
    for (let i = 0, j = array.length; i < j; i += 1) {
        const current = array[i];
        if (predicate(current) === true) {
            numMatches += 1;
        }
    }
    return numMatches;
}

const numFound = getNumMatches(dataset, (item) => {
    return item === 2;
});

alert(numFound); // should alert 3

_/DEMO:https://jsfiddle.net/57en9nar/1/

6
Ian
var dataset = [2,2,4,2,6,4,7,8], count = {}

dataset.forEach(function(el){
    count[el] = count[el] + 1 || 1
});

console.log(count)

//  {
//    2: 3,
//    4: 2,
//    6: 1,
//    7: 1,
//    8: 1
//  }
5
Manolis

Vous pouvez utiliser la méthode array.reduce(callback[, initialValue]) dans JavaScript 1.8 

var dataset = [2,2,4,2,6,4,7,8],
    dataWithCount = dataset.reduce( function( o , v ) {

        if ( ! o[ v ] ) {
            o[ v ] = 1 ;  
        }  else {
            o[ v ] = o[ v ] + 1;
        }      

        return o ;    

    }, {} );

// print data with count.
for( var i in  dataWithCount ){
     console.log( i + 'occured ' + dataWithCount[i] + 'times ' ); 
}

// find one number
var search = 2,
    count = dataWithCount[ search ] || 0;
3
rab

Vous pouvez compter tous les éléments d'un tableau, sur une seule ligne, en utilisant une réduction. 

[].reduce((a,b) => (a[b] = a[b] + 1 || 1) && a, {})

Cela donnera un objet dont les clés sont les éléments distincts du tableau et les valeurs le nombre d'occurrences d'éléments dans le tableau. Vous pouvez ensuite accéder à un ou plusieurs comptes en accédant à une clé correspondante sur l'objet.

Par exemple, si vous deviez encapsuler ce qui précède dans une fonction appelée count():

function count(arr) {
  return arr.reduce((a,b) => (a[b] = a[b] + 1 || 1) && a, {})
}

count(['example'])          // { example: 1 }
count([2,2,4,2,6,4,7,8])[2] // 3
2
justin.m.chase

J'ai trouvé plus utile de finir avec une liste d'objets avec une clé pour ce qui est compté et une clé pour le compte:

const data = [2,2,4,2,6,4,7,8]
let counted = []
for (var c of data) {
  const alreadyCounted = counted.map(c => c.name)
  if (alreadyCounted.includes(c)) {
    counted[alreadyCounted.indexOf(c)].count += 1
  } else {
    counted.Push({ 'name': c, 'count': 1})
  }
}
console.log(counted)

qui retourne: 

[ { name: 2, count: 3 },
  { name: 4, count: 2 },
  { name: 6, count: 1 },
  { name: 7, count: 1 },
  { name: 8, count: 1 } ]

Ce n'est pas la méthode la plus propre, et si quelqu'un sait comment obtenir le même résultat avec reduce faites le moi savoir. Cependant, cela donne un résultat assez facile à utiliser.

0
crash springfield

Tout d'abord, vous pouvez utiliser la solution Brute Force en optant pour la recherche linéaire.

public int LinearSearchcount(int[] A, int data){
  int count=0;
  for(int i=0;i<A.length;i++) {
    if(A[i]==data) count++;
  }
  return count;
}

Cependant, pour aller avec cela, nous obtenons la complexité du temps comme O (n) .Mais en allant avec la recherche binaire, nous pouvons améliorer notre complexité.

0
Balaji Mj