Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

318
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda