Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

316
Views
Sort Array by Element Frequency JavaScript

I want to sort an array by element frequency. My code works for arrays of strings, but not for arrays of numbers:

const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0);

function frequencySort(arr){
  let d = {}
  arr.forEach(i => d[i] = countOccurrences(arr,i))
  arr.sort(function(a,b){
    return d[b] - d[a]
  })
  
  return arr
}



frequencySort(['a','b','b','b','c','c'])) returns [ 'b', 'b', 'b', 'c', 'c', 'a' ]

frequencySort([4, 6, 2, 2, 6, 4, 4, 4]) returns [ 4, 4, 4, 4, 6, 2, 2, 6 ]

Could anyone help me out? Thanks!

about 4 years ago · Juan Pablo Isaza
3 answers
Answer question

0

The only reason your letters worked is because you didn't have the same number of any two letters, where in your numbers, you have 2 of both 2 and 6.

Here's your snippet, but with 2 a's and 2 c's. You'll see it's out of order just like the numbers.

const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0);

function frequencySort(arr){
  let d = {}
  arr.forEach(i => d[i] = countOccurrences(arr,i))
  arr.sort(function(a,b){
    return d[b] - d[a]
  })
  
  return arr
}

console.log(frequencySort(['a','b','b','b','c','c', 'a']))

You need a way to sort instances that have the same number of occurrences. I adapted your forEach loop to give the last index of each letter to your b object and then changed your sort to use that index in case the number of occurrences is the same.

const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0);

function frequencySort(arr){
  let d = {}
  arr.forEach((i,index) => d[i] = {
    num: countOccurrences(arr,i),
    i: index
  });
  arr.sort(function(a,b){
    let diff = d[b].num - d[a].num;
    if(diff == 0)
      diff = d[b].i - d[a].i;
    return diff;
  })
  
  return arr
}

console.log(frequencySort(['a','b','b','b','c','c', 'a']))
console.log(frequencySort([4, 6, 2, 2, 6, 4, 4, 4]));

about 4 years ago · Juan Pablo Isaza Report

0

In your array of numbers you have the same amount of the number 2 as 6 and your sorting function doesn't care about the actual values it just cares about their counts. So in your example 2 and 6 both have the same priority.

You want to adjust your sorting function to compare values of elements if they have the same amount of occurrences. You'll need to implement separate comparisons for all the data types you want to accept and decide if you want ascending/descending order.

Here is a basic example for number and string elements:

const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a + 1 : a), 0);

function frequencySort(arr){
  let d = {}
  arr.forEach(i => d[i] = countOccurrences(arr,i))
  arr.sort(function(a,b){
    const r = d[b] - d[a]
    if (r != 0) return r
    switch (typeof d[a]) {
    case 'number': return a - b
    case 'string': return a.localeCompare(b)
    default: return 0
    }
  })
  
  return arr
}



console.log(frequencySort(['a','b','b','b','c','c'])) // returns [ 'b', 'b', 'b', 'c', 'c', 'a' ]

console.log(frequencySort([4, 6, 2, 2, 6, 4, 4, 4])) // returns [ 4, 4, 4, 4, 2, 2, 6, 6 ]

about 4 years ago · Juan Pablo Isaza Report

0

A possible approach would first collect all equal array items within an item specific group array by a reduce task ...

console.log(
  "grouped ['a','b','b','b','c','c'] ...",
  ['a','b','b','b','c','c'].reduce((index, item) => {
    const groupList =
      index[`${ (typeof item) }_${ item }`] ??= [];

    groupList.push(item);

    return index;
  }, {})
);
console.log(
  "grouped [4, 6, 2, 2, 6, 4, 4, 4,'4','2','2'] ...",
  [4, 6, 2, 2, 6, 4, 4, 4,'4','2','2'].reduce((index, item) => {
    const groupList =
      index[`${ (typeof item) }_${ item }`] ??= [];

    groupList.push(item);

    return index;
  }, {})
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

The final computation then has to transform ... via Object.values ... the temporary result (as shown above) into an array of arrays of equal items where the former gets 1stly sorted by each array's length (indicates the items frequency) and 2ndly, for arrays of equal length', by a locale compare of each array's first item. The final result is the sorted array's flatted version ...

function sortItemsByFrequency(arr) {

  const groupedItems = arr.reduce((index, item) => {
    const groupList =
      index[`${ (typeof item) }_${ item }`] ??= [];

    groupList.push(item);

    return index;
  }, {});

  return Object
    .values(groupedItems)
    .sort((a, b) =>
      // - sort by frequency first indicated by an
      //   array's length.
      // - the higher frequency count wins.
      b.length - a.length ||
      // in case of equal frequency counts do a
      // locale compare of both array's first items.
      b[0].toLocaleString().localeCompare(a[0].toLocaleString())
    )
    .flat();
}

console.log(
  "sortItemsByFrequency(['a','b','b','b','c','c']) ...",
  sortItemsByFrequency(['a','b','b','b','c','c'])
);
console.log(
  "sortItemsByFrequency([4, 6, 2, 2, 6, 4, 4, 4,'4','2','2']) ...",
  sortItemsByFrequency([4, 6, 2, 2, 6, 4, 4, 4,'4','2','2'])
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!