# Find array elements frequency, then return sorted associative array

Hi Campers!

So I have an array of strings, like the following `letters = ['a', 'b', 'b', 'c', 'b', 'a', 'a', 'b', 'c', 'c', 'b']`

My goal is to find the frequency of each element , and then return an associative array sorted in descending order based on the frequency (and if the frequency is the same, alphabetically), such as `[{letter: "b", frequency: 5}, {letter: "a", frequency: 3}, {letter: "c", frequency: 3}]`

Any Ideas on how to approach this?

Thanks!

2 Likes

Have you attempted to write any sort of algorithm? I would first start thinking how you would accomplish this if you were given a long list of letters such as and how you would keep track of them with pen and paper. Your algorithm will be very much like that process.

2 Likes

Solved. A bubble sort has done the trick.

So what was your final solution?

I did the following:

``````const letters = ['e','c','b', 'a', 'b', 'b', 'a', 'a', 'b', 'c', 'c', 'b'];

const letterFrequencies = letters
.reduce((freqs, letter) => Object
.assign(freqs, { [letter]: (freqs[letter] || 0 ) + 1 }), {});

const letterFrequencyArr = Object
.keys(letterFrequencies)
.map(letter => ({ letter, frequency: letterFrequencies[letter] }));

letterFrequencyArr.sort((a, b) => b.frequency - a.frequency || a.letter.localeCompare(b.letter));

console.log(letterFrequencyArr);
/* displays the following in the console
[
{ letter: 'b', frequency: 5 },
{ letter: 'a', frequency: 3 },
{ letter: 'c', frequency: 3 },
{ letter: 'e', frequency: 1 }
]
*/
``````
1 Like

A very elegant solution, Thanks!
Here’s my mammoth function:

``````var letters = ['a', 'b', 'b', 'c', 'b', 'a', 'a', 'e', 'b', 'c', 'c', 'b'];

function countSortDescend(arr) {
return reverseBubbleSortBy(count(arr), l => l.frequency);

function reverseBubbleSortBy(array, cb) {
for (let n = 1; n < array.length; n++) {
for (let i = 0; i < array.length - n; i++) {
if (cb(array[i]) < cb(array[i + 1])) swap(array, i, i + 1);
}
}
return array;
}

function count(array) {
var result = [],
dups = array.length;
for (let i = 0; i < dups; i++) {
let frequency = 1;
for (let ii = i + 1; ii < dups; ii++) {
if (array[i] === array[ii]) {
frequency++;
swap(array, ii, dups - 1);
ii--;
dups--;
}
}
result.push({
value: array[i],
frequency
});
}

return result;
}

function swap(arr, i1, i2) {
var temp = arr[i1];
arr[i1] = arr[i2];
arr[i2] = temp;
}
}

console.log(countSortDescend(letters));

/*

[ { value: 'b', frequency: 5 },
{ value: 'a', frequency: 3 },
{ value: 'c', frequency: 3 },
{ value: 'e', frequency: 1 } ]

*/

``````

Pass the following array to your function and you will see it does not actually do what you wanted.

``````var letters = ['e','c','b', 'a', 'b', 'b', 'a', 'a', 'b', 'c', 'c', 'b'];
``````

``````[ { value: 'b', frequency: 5 },
{ value: 'c', frequency: 3 },
{ value: 'a', frequency: 3 },
{ value: 'e', frequency: 1 }
]
``````

when it should return:

``````[ { value: 'b', frequency: 5 },
{ value: 'a', frequency: 3 },
{ value: 'c', frequency: 3 },
{ value: 'e', frequency: 1 }
]
``````

The ‘a’ should come before the ‘c’ based on the requirements you described originally.