【问题标题】:Sort Array by Element Frequency JavaScript按元素频率 JavaScript 对数组进行排序
【发布时间】:2021-12-03 02:49:44
【问题描述】:

我想按元素频率对数组进行排序。我的代码适用于字符串数组,但不适用于数字数组:

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 ]

谁能帮帮我?谢谢!

【问题讨论】:

  • @M4rs3l ... 从所有提供的解决方案/方法中,还有什么问题吗?
  • 我完全是新来的,忘记了这一点。现在浏览答案,一切都非常有帮助。 @PeterSeliger 我的赞成票尚未计算在内,但已记录在案。

标签: javascript arrays sorting frequency


【解决方案1】:

您的字母有效的唯一原因是因为您没有任何两个字母的相同数字,在您的数字中,您有 2 和 6。

这是您的 sn-p,但有 2 个 a 和 2 个 c。你会发现它和数字一样乱序。

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']))

您需要一种方法来对出现次数相同的实例进行排序。我调整了您的 forEach 循环,将每个字母的最后一个索引提供给您的 b 对象,然后更改您的排序以使用该索引,以防出现次数相同。

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]));

【讨论】:

    【解决方案2】:

    它与元素是字母或数字无关。在你的字母数组中,每个字母都有唯一的出现次数(3、2、1),因此它们按照你想要的方式排序。

    但是,在您的 numbers 数组中,“2”和“6”都出现了 2 次。因此,您的排序回调函数为它们返回 0,并且它们被 sort 函数视为相同的顺序。

    【讨论】:

      【解决方案3】:

      在您的数字数组中,数字 2 的数量与 6 的数量相同,并且您的排序函数不关心实际值,它只关心它们的计数。因此,在您的示例 2 和 6 中,两者具有相同的优先级。

      如果元素的出现次数相同,您想调整排序功能以比较元素的值。 您需要对要接受的所有数据类型进行单独比较,并决定是否要升序/降序。

      以下是数字和字符串元素的基本示例:

      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 ]

      【讨论】:

        【解决方案4】:

        一种可能的方法是首先通过reduce 任务收集项目特定组数组中所有相等的数组项...

        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; }

        然后最终的计算必须通过Object.values...将临时结果(如上所示)转换为相等项数组的数组,其中前者首先得到sorted 每个数组的长度(表示项目的频率),其次,对于等长的数组,每个数组的第一项的locale compare。最终结果是排序后数组的flatted 版本...

        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; }

        【讨论】:

          猜你喜欢
          • 2020-10-19
          • 2015-10-18
          • 1970-01-01
          • 2019-06-10
          • 1970-01-01
          • 2020-08-26
          • 1970-01-01
          • 1970-01-01
          • 2021-07-28
          相关资源
          最近更新 更多