Skip to content

Instantly share code, notes, and snippets.

@ralphcrisostomo
Created July 19, 2012 07:43
Show Gist options
  • Save ralphcrisostomo/3141412 to your computer and use it in GitHub Desktop.
Save ralphcrisostomo/3141412 to your computer and use it in GitHub Desktop.
Javascript: Count duplicates in an array
/**
Problem:
You have a javascript array that likely has some duplicate values and you would like a count of those values.
Solution:
Try this schnippet out.
*/
function compressArray(original) {
var compressed = [];
// make a copy of the input array
var copy = original.slice(0);
// first loop goes over every element
for (var i = 0; i < original.length; i++) {
var myCount = 0;
// loop over every element in the copy and see if it's the same
for (var w = 0; w < copy.length; w++) {
if (original[i] == copy[w]) {
// increase amount of times duplicate is found
myCount++;
// sets item to undefined
delete copy[w];
}
}
if (myCount > 0) {
var a = new Object();
a.value = original[i];
a.count = myCount;
compressed.push(a);
}
}
return compressed;
};
// It should go something like this:
var testArray = new Array("dog", "dog", "cat", "buffalo", "wolf", "cat", "tiger", "cat");
var newArray = compressArray(testArray);
/*
console: [
Object { value="dog", count=2},
Object { value="cat", count=3},
Object { value="buffalo", count=1},
Object { value="wolf", count=1},
Object { value="tiger", count=1}
]
*/
@davidnagli
Copy link

Also, after some further testing and analysis, I found that both of my ideas are significantly faster than the original gist.

I ran all three on an array of 100,000 random numbers between 0-7

my map idea: 1.974 ms
my original idea: 9.172 ms
gist idea: 16.987644 SECONDS!!!

The performance difference was staggering...

@akilmakda
Copy link

@davidnagli ty man.

@msqaddura
Copy link

msqaddura commented Feb 7, 2018

//THIS IS JUST FOR FUN, ALTHOUGH IT IS WORKING AWESOMELY!!
let bag={};
["NA","NA","NA","NA","NA","NA","NA","NA","NA","BATMAN"].forEach((item)=>{
    bag[item] = bag[item]?++bag[item]:1;
})
return bag;

@Lycurgue
Copy link

Hi,

I'm using the original counter up there: array_dupplicate_counter.js

The script produce an object not an array.
I'd like to sort the object based on the value property not on the count property.
I tried many things with no avail.

Is someone know how to sort that kind of object?

Thanks

François

@Yene-Me
Copy link

Yene-Me commented Mar 3, 2018

great work

@vishalbiradar
Copy link

How to use this code in typescript ?? I am unable to use as it is.
Please help me....

@cablegunmaster
Copy link

cablegunmaster commented Apr 30, 2018

Thanks for the work :D ! Handy and works great!

Typescript version:

let compressArray = (original: Array) => {

    let compressed = [];
    // make a copy of the input array
    let copy = original.slice(0);

    // first loop goes over every element
    for (let i = 0; i < original.length; i++) {

        let myCount = 0;
        // loop over every element in the copy and see if it's the same
        for (let w = 0; w < copy.length; w++) {
            if (original[i] == copy[w]) {
                // increase amount of times duplicate is found
                myCount++;
                // sets item to undefined
                delete copy[w];
            }
        }

        if (myCount > 0) {
            let a = {};
            a['value'] = original[i];
            a['count'] = myCount;
            compressed.push(a);
        }
    }
    return compressed;
};

@tedico
Copy link

tedico commented Aug 30, 2018

@davidnagli thanks a bunch man! I learned quite a few things from you today.

@MirzaChilman
Copy link

thanks for both author and @davidnagli

@alexxx-gt
Copy link

God bless you :)

@jimmleon
Copy link

jimmleon commented Nov 8, 2018

Very useful!
Thanks both of you @ralphcrisostomo
and @davidnagli for the gain-performance implementation and the explanation bonus!

@williamlsh
Copy link

function countDup(arr = []) {
  const set = new Set(arr);
  const uniqueArr = Array.from(set);
  if (uniqueArr.length === arr.length) return;

  const map = new Map();
  uniqueArr.forEach((uniqueVal) => {
    let n = 0;
    arr.forEach((val) => {
      if (val === uniqueVal) {
        n++;
      }
    });
    map.set(uniqueVal, n);
  });
  console.log('newMap ', map);
  for (const [key, val] of map) {
    console.log(key, val);
  }
}

@navinAdhe
Copy link

navinAdhe commented Jul 30, 2019

array = ['Apples', 'Oranges', 'Apples', 'Strawberries', 'Apples'];

For a one liner to get unique values and their counts and put them in a dictionary :

reducedArray = array.reduce((acc, datum) => { 
                              let count = acc[datum];
                              acc[datum] = count === undefined ? 1 : ++count;
                              return acc;
                           }, {});

acc = accumulator that indexes according to datum
and returns a key value pair with key as datum and count as the number of times the datum appears in the array.

o/p: (try console.log(reducedArray))
Apples: 3
Oranges: 1
Strawberries: 1

@navinAdhe
Copy link

array = ['abc', '123', 'abc', 'xyz', 'abc'];

For a one liner using reduce to count unique distinct values and put them in a dictionary:

reducedArray= array.reduce((acc, datum) => {
      let count= acc[datum];
      acc[datum] = count === undefined ? 1 : ++count;
      return acc;
    }, {});

acc: indexes the dictionary using datum and increments the count if it finds a duplicate

console: 
abc: 3
123: 1
xyz: 1

@saiteja-aakula
Copy link

saiteja-aakula commented Oct 15, 2019

@davidnagli Thanks Buddy.. it really helped me with just one line code change.
appreciated

@amyspeed
Copy link

amyspeed commented Feb 3, 2020

Thanks for this @ralphcrisostomo! I implemented one change, though. I needed to use data repeatedly in different ways. The "delete copy[w]" on line 27 line really threw my data off. I changed it for "i++" and was successful in keeping my data intact. Thanks again!!

@zerosimms
Copy link

Had to search high and low for this solution, every tutorial and answer before was only outputting in the console. You are a legend! Thanks you!

@joshdrumz
Copy link

@williamlsh those first three lines can be reduced to one via ES6 spread syntax!

let uniqueArr = [...new Set(arr)];

@sbwill526
Copy link

Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment