1

I am trying to sort some numbers, and I want to count the number of times that an array has a certain number.

My question is more about the structure of an the array than the counting the number part. I would like to build an array that looks like this below.

let numbers = [1,2,3,4,4,4,5,5,6];

How could I make the data structure below?

numbers[3].count // this will be equal to 3 after I loop through;

How do I make each part of the array have an object parameter?

Do I just loop through like so?

for (let i = 0; i < numbers.length; i++){
  numbers[i] = {
    count: 0
  }
}

I understand this wont give me the right count, but I don't care about that part of the problem. I would like to solve that on my own. I just need to be sure that this is the correct way to add the object parameters.

Alexander Nied
  • 12,804
  • 4
  • 25
  • 45
  • Yes, that seems a fine solution, though you'll want to store the value at the index in the object as well as othewise you'll just be overwriting it. So `numbers[i] = {value: numbers[i], count: 0};` – pilchard Feb 23 '22 at 01:31
  • 2
    Keep in mind that you're not adding keys to the array, but making each element of the array an object which has keys. `[{count: 0}, {count: 0}]` – pilchard Feb 23 '22 at 01:37
  • Right, that is what I want to do. But from your first comment are you saying that if I ran that code as is then, numbers[0] would be equal to 0? If so, How can I get it so that numbers[0] = 1 and numbers[0].count = 0 – Alex Barbosa Feb 23 '22 at 01:47
  • @AlexBarbosa A value in JavaScript cannot simultaneously be multiple types (e.g. `number` and `object`). Any value that has properties in JavaScript is an `object`. If you want to store multiple values (e.g. a value and a count), you'd need to store them on properties of an object (or as elements in a sub-array). – jsejcksn Feb 23 '22 at 01:53
  • 1
    @AlexBarbosa You can initialize a [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) outside the loop, and store the information about each array element as you iterate. And you can do all of this inside a [reducer function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) which returns the map. – jsejcksn Feb 23 '22 at 02:00
  • 2
    The post [Why can't I add properties to a string object in javascript?](https://stackoverflow.com/q/5201138/6831341) provides some interesting insight into the problem you are facing. [This answer discusses using the type constructor to achieve something to this affect](https://stackoverflow.com/a/5326882/6831341)-- you could probably do something similar with `new Number()`, but then you'd be stuck leveraging the `.valueOf()` method to get the number back out, and it wouldn't be very idiomatic JS, so I'm not sure if it is really an elegant solution. – Alexander Nied Feb 23 '22 at 02:09

5 Answers5

-1

I would build these functions on my own. Something like this You can copy and paste this in the console of your browser.

// my numbers list
const numbers = [1, 2, 3, 4, 4, 4, 5, 5, 6];
// reduced to unique entries
const uniques = [...new Set(numbers)];
// function to count occurrences in my list of number
const count = (n) => numbers.filter((num) => num === n).length;
// you can test here
console.log(`counting ${uniques[4]}s`, count(uniques[4]));
// get these as object
console.log(uniques.map((unique) => ({[unique]: count(unique)})))
Caio Koiti
  • 89
  • 1
  • 3
-1

Simplest way to achieve this by using Array.forEach().

let numbers = [1,2,3,4,4,4,5,5,6];

const obj = {};

numbers.forEach((item) => {
    obj[item] = (obj[item] || 0) + 1;
});

console.log(obj);
Debug Diva
  • 26,058
  • 13
  • 70
  • 123
-1
const numbers = [1,2,3,4,4,4,5,5,6];
 
const counts = {};

numbers.forEach((x) => counts[x] = (counts[x] || 0) + 1);

console.log(counts)
Peter Csala
  • 17,736
  • 16
  • 35
  • 75
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Feb 23 '22 at 08:47
-1

You can use the Array#reduce() method to group elements together into sub arrays. Since arrays have a length property that gives the the number of elements this can be applied to each group of like elements. We do not need to create a new count property.

let numbers = [1,2,3,4,4,4,5,5,6];

const freq = numbers.reduce(
    (acc,cur) => ({...acc,[cur]:(acc[cur] || []).concat(cur)})
);

console.log( freq[4] );
console.log( freq[4].length );

Alternatively, you can put the numbers in an object and get all the unique elements, then for each unique element define a get property that groups like elements together using the Array#filter() method. Again, the length array property can be used to return the number of elements for each unique element.

const o = {numbers: [1,2,3,4,4,4,5,5,6]};
o.uniq = [...new Set(o.numbers)];
o.uniq.forEach(n => Object.defineProperty(
    o,n,{get:() => o.numbers.filter(num => num === n)}
));
console.log( o[5] );
console.log( o[5].length );
PeterKA
  • 24,158
  • 5
  • 26
  • 48
-2

Reduce is perfect for these kinds of problems.

const numbers = [1,2,3,4,4,4,5,5,6];

const countedObject = numbers.reduce((tmpObj, number) => {
  if (!tmpObj[number]) {
    tmpObj[number] = 1;
  } else {
    tmpObj[number] += 1;
  }
  return tmpObj
}, {});


console.log(countedObject);

if you feel the need to nest it further you can of course do this. But if count is the only property you need, I'd suggest sticking to the first version.

const numbers = [1,2,3,4,4,4,5,5,6];

const countedObject = numbers.reduce((tmpObj, number) => {
  if (!tmpObj[number]) {
    tmpObj[number] = {count: 1};
  } else {
    tmpObj[number].count += 1;
  }
  return tmpObj
}, {});


console.log(countedObject);
arthurDent
  • 818
  • 9
  • 13