2

Link to Codewars challenge

I've been able to create a frequency map for the letter frequency count for a string:

function letterFrequency(text){
    text = text.toLowerCase();
    let map = {};
    let array = text.split('');
    array.forEach((value, index) => {
      if (!map[value]) {
        map[value] = 0;
      }
      map[value] += 1;
    });
    return Object.entries(map).filter((el) => el[0] !== ' ')
    //sorts array according to count
    .sort((a, b) => b[1] - a[1]);
    //how to sort alphabetically when letters have same count?
}
console.log(letterFrequency('aaAabb dddDD hhcc'));

But I've not been able to figure out how to sort alphabetically when frequency counts are the same.

I.e.

[['d',5], ['a',4], ['b',2], ['h',2], ['c',2]]

Should instead be:

[['d',5], ['a',4], ['b',2], ['c',2], ['h',2]]

How can I keep frequency count as the main sorting priority, but then also sort alphabetically after sorting by frequency?

Also trying this unfortunately did not have any effect:

function letterFrequency(text){
    text = text.toLowerCase();
    let map = {};
    let array = text.split('');
    array.forEach((value, index) => {
      if (!map[value]) {
        map[value] = 0;
      }
      map[value] += 1;
    });
    return Object.entries(map).filter((el) => el[0] !== ' ')
    .sort((a, b) => b[1] - a[1])
    .sort((a, b) => a[0] - b[0]);
}
HappyHands31
  • 4,001
  • 17
  • 59
  • 109
  • You could use the answer here: https://stackoverflow.com/a/6913821/215552; just pass indexes instead of property names. – Heretic Monkey Oct 08 '19 at 18:33
  • Possible duplicate of [Javascript: Sort Multidimensional Array](https://stackoverflow.com/questions/6993302/javascript-sort-multidimensional-array) – Heretic Monkey Oct 08 '19 at 18:34

3 Answers3

2

You can "or" (||) the count difference with the result of localeCompare so that if the count difference is 0, localeCompare takes precedence:

function letterFrequency(text) {
  text = text.toLowerCase();
  let map = {};
  let array = text.split('');
  array.forEach((value, index) => {
    if (!map[value]) {
      map[value] = 0;
    }
    map[value] += 1;
  });
  return Object.entries(map).filter((el) => el[0] !== ' ')
    .sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]));
}

console.log(letterFrequency('dadbahddbccdh'));
slider
  • 12,810
  • 1
  • 26
  • 42
1

you can do two sorts. sort by alphabetical, then by number, that way the alphabetical order is preserved when you do your numerical sort after

var x = [['d',5], ['a',4], ['b',2], ['h',2], ['c',2]];
x.sort(function(a, b){
    if(a[0] < b[0]) { return -1; }
    if(a[0] > b[0]) { return 1; }
    return 0;
}).sort(function(a, b){
    return b[1] - a[1]})
leo
  • 276
  • 2
  • 6
1

Simple and easy steps with JavaScript based on Object Creation, Array-Sorting, and String. The same solution can be implemented in any language.

var frequencySort = function(s) {

let obj={},string='';
for(let i=0;i<s.length;i++) {
    if(obj[s[i]]){
        obj[s[i]] += 1;
    } else {
        obj[s[i]] = 1
    }
}
let array = Object.entries(obj);
for(let i=0;i<array.length;i++){
    for(let j=i+1;j<array.length;j++){
        if(array[j] && array[j][1] > array[i][1]){
            let temp = array[i];
            array[i] = array[j];
            array[j] = temp;
        }
    }
}
for(let i=0;i<array.length;i++){
    for(let j=0;j<array[i][1];j++){
        string += array[i][0]
    }  
}
return string
};
Ashish
  • 2,026
  • 17
  • 19