0

So I have this code which should count occurrences of the numbers that are inputted with an array.

  let counts = {};

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

I don't get why it sorts the input that I provide? For example if I input [1,3,2] on the output, my object says:

1:1 2:1 3:1

Thanks in advance.

  • 1
    Objects have no implicit "order" – Jamiec Jul 17 '18 at 09:45
  • you have put the value of `arr[i]` as a key. Of course,it will get sorted as `arr[i]` is an integer. – david Jul 17 '18 at 09:45
  • Object properties were unordered for a long time, and should still be treated as such in most cases. These days, object properties are ordered ascending for integer indexes. `console.log` output does not have to conform to that order, but usually does. – ASDFGerte Jul 17 '18 at 09:46
  • you can check this link https://stackoverflow.com/questions/5525795/does-javascript-guarantee-object-property-order same issue – Ahmed Yousif Jul 17 '18 at 09:54
  • Possible duplicate of [Does JavaScript Guarantee Object Property Order?](https://stackoverflow.com/questions/5525795/does-javascript-guarantee-object-property-order) – Ahmed Yousif Jul 17 '18 at 09:54
  • 1
    @AhmedYousif that topic is outdated, and the cause for a lot of confusion. See bolded comments that warn of this issue. – ASDFGerte Jul 17 '18 at 09:56

2 Answers2

1

You could take a Map which maintains the order and render an array of objects as result.

let counts = new Map,
    arr = [1, 3, 2];

for (let i = 0; i < arr.length; i++) {
    let num = arr[i];
    counts.set(num, (counts.get(num) || 0 ) + 1);
}

console.log(Array.from(counts.entries(), ([value, count]) => ({ value, count })));
Nina Scholz
  • 323,592
  • 20
  • 270
  • 324
0

You're using an Object to capture the results, and the keys have no implicit order - however as you've discovered they effectively do for integer keys.

If you want to maintain order, perhaps use an array of objects with properties for your key and count - however you will have the problem of finding the right item to increment its count.

You could achieve this with an array to maintain order and an object to provide fast lookup:

let result = {
   lookup: {},
   counts: []
};

var arr = [1,3,2]
for (let i = 0; i < arr.length; i++) {
  let num = arr[i];
  var item = result.lookup[num];
  if(!item){
       item = {key:num,count:0}
       result.counts.push(item);
       result.lookup[num] = item;
  }
  item.count++;
}


console.log(result.counts);
Jamiec
  • 118,012
  • 12
  • 125
  • 175
  • Great! This is the one I was looking for, I just started programming and still need to learn a lot :) Thanks! – Kamil Sławecki Jul 17 '18 at 09:55
  • @KamilSławecki [Nina's anser](https://stackoverflow.com/a/51378289/219661) is basically doing the same thing but much easier - check that one out – Jamiec Jul 17 '18 at 09:58