Check how many times a number appears in the array

Asked

Viewed 2,304 times

5

I have an array with the following values:

let arrey = ["1","1","1","2","2","2"];

As it is possible to check how many times the number 1 appears and how many times the number 2 appears, for example, these numbers are changed each time I run my program, I need to check how many times the specified number appeared in the array, or the return should be another one like that:

let arrey2 = [ 

  {
     "numero": 1,
     "quantidade": 3
  },
  {
     "numero": 2,
     "quantidade": 3
  }
]

The code:

function itemCount(arrey){
    let valor = arrey[0];
    let length = arrey.length
    let index = []
    let contador =  0
    let x = 0
    let bol;
    while(x < length){
        for(let i = 0; i < arrey.length; i++){
            if(arrey[x] === valor){
                console.log(arrey[x])
                contador += 1
            }
        }
        
        let obj = {
            "produto_id": arrey[x],
            "quantidade": contador
        }
        if(index.length > 0){
            index.forEach(itemArrey => {
               if(itemArrey.produto_id === obj.produto_id){
                   bol = false;
               }else{
                   bol = true;
               }
            });
            if(bol == true){
                index.push(obj);
            }
        }else if(index.length == 0){
            index.push(obj);
        }
        x++
    }
    return index;
}

Passing the following array as input:

let arrey = ['1','1','2','2','2'];
intemCount(arrey);

The output of this my code is as follows:

(2) [{…}, {…}]
0: {produto_id: "1", quantidade: 5}
1: {produto_id: "2", quantidade: 10}
length: 2
__proto__: Array(0)

3 answers

7


Although it is possible to make your code work, I think it is worth understanding that there are other (simpler and more efficient) ways to do what you need.

If you are always working with an array of primitives (numbers, strings, etc.), you can create an object followed by the "count" of times it appears (by default, zero). So, you only need to iterate once over the array.

Something like that:

function countItems(arr) {
  const countMap = Object.create(null);

  for (const element of arr) {
    if (!countMap[element]) {
      // Se ainda não existir elemento, definimos como um, já que
      // estamos na primeira ocorrência.
      countMap[element] = 1;
    } else {
      // Caso contrário, incrementamos um no número atual.
      countMap[element] += 1;
    }
  }
  
  return countMap;
}

const arr = ['1', '1', '2', '2', '2'];
console.log(countItems(arr));

You can still simplify the above code when using short-circuit:

function countItems(arr) {
  const countMap = Object.create(null);

  for (const element of arr) {
    // Basicamente, estamos dizendo: atribua à `countMap[element]` o valor
    // atual (ou zero, caso não existir) somado ao número 1.
    countMap[element] = (countMap[element] || 0) + 1;
  }
  
  return countMap;
}

const arr = ['1', '1', '2', '2', '2'];
console.log(countItems(arr));

And to transform the countMap in the output array you expect, one option is to use the Object.entries together with map:

function countItems(arr) {
  const countMap = Object.create(null);

  for (const element of arr) {
    // Basicamente, estamos dizendo: atribua à `countMap[element]` o valor
    // atual (ou zero, caso não existir) somado ao número 1.
    countMap[element] = (countMap[element] || 0) + 1;
  }

  return Object.entries(countMap).map(([value, count]) => ({
    numero: value,
    quantidade: count
  }));
}

const arr = ['1', '1', '2', '2', '2'];
console.log(countItems(arr));

The problem is that this "translation" adds a slight cost (imperceptible in your case, since I think you will work with few items), since another repetition will have to be done, for the number of properties of countMap, that is, the number of unique array items.

I personally prefer to simply return the object countMap. Nothing stops you from using the Object.entries in simply another part of the code.

  • 3

    Wow! Just awesome! Thank you so much for giving me this class, I was complicating things too much when it wasn’t this seven-headed animal that I was thinking about. In addition to giving me a lesson passed me new knowledge in JS. Thank you very much!!!!!

6

One possibility is to use the method Array.prototype.reduce() performing a reducing function for each element of the Array, resulting in a single return value. In your case reduce() can be used to assemble and return an object that each of its property is named by the distinct elements of the Array the input and value of each of these properties are a sub-object whose properties would be "número" and "quantidade".

let arr = ["1", "1", "1", "2", "2", "2", "4", "4"];


let resultado = arr.reduce((acc, val) => {
  if (!acc[val]) acc[val] = {
    "número": val,
    "quantidade": 1
  };
  else acc[val]["quantidade"]++;
  return acc;
}, {});


console.log(resultado);

To remove the pseudo-indices suffice to input the result using the method Array.prototype.map() and return its value, to get one by one the input of the result use the method Object.entries() which returns an array of pairs [key, value] enumerable of a given object, index 0 is the key index 1 is the value.

let arr = ["1", "1", "1", "2", "2", "2", "4", "4"];


let resultado = arr.reduce((acc, val) => {
  if (!acc[val]) acc[val] = {
    "número": val,
    "quantidade": 1
  };
  else acc[val]["quantidade"]++;
  return acc;
}, {});


console.log(Object.entries(resultado).map((val) => {
  return val[1];
}));

UPDATE:

As suggested by Luiz Felipe the use of the method Object.values() can greatly simplify the code. Object.values() returns an array with the properties values of a given object

let arr = ["1", "1", "1", "2", "2", "2", "4", "4"];


let resultado = arr.reduce((acc, val) => {
  if (!acc[val]) acc[val] = {
    "número": val,
    "quantidade": 1
  };
  else acc[val]["quantidade"]++;
  return acc;
}, {});


console.log(Object.values(resultado));

  • 1

    Good answer, Augusto! Only at the end that could change the Object.entries for Object.values to get even better! :-)

  • 1

    @Luizfelipe, I made an issue containing your suggestion. I found it very good, thank you very much.

3

The expression counts[x] || 0 returns the value of counts[x] if defined, otherwise 0.
Then just add one and configure it again in the object and the count is completed.

let arrey = ["1","1","2","2","2"];
var counts = {};
arrey.forEach(function(x) { counts[x] = (counts[x] || 0)+1; });

console.log(counts);

Here have the one I posted and more

Browser other questions tagged

You are not signed in. Login or sign up in order to post.