Younes
June 18, 2019, 11:38pm
#1
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

Younes
June 19, 2019, 5:13pm
#3
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

Younes
June 19, 2019, 6:20pm
#5
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'];
```

Your solution returns:

```
[ { 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.