按数组元素的出现情况对数组进行排序



我正在寻找一种根据数组元素的出现情况对数组进行排序的优雅方法。

例如,在:中

['pear', 'apple', 'orange', 'apple', 'orange', 'apple']

输出应该看起来像

['apple', 'orange', 'pear']

我曾尝试循环遍历该数组,并将出现的情况保存在另一个临时数组中,但这个解决方案非常糟糕。

这需要两个循环。

    var arr = ['pear', 'apple', 'orange', 'apple', 'orange', 'apple'];
    //find the counts using reduce
    var cnts = arr.reduce( function (obj, val) {
        obj[val] = (obj[val] || 0) + 1;
        return obj;
    }, {} );
    //Use the keys of the object to get all the values of the array
    //and sort those keys by their counts
    var sorted = Object.keys(cnts).sort( function(a,b) {
        return cnts[b] - cnts[a];
    });
    console.log(sorted);

将值映射到水果中→计数关联对象:

var counted = fruits.reduce(function (acc, fruit) {
    if (acc[fruit]) {
        acc[fruit]++;
    } else {
        acc[fruit] = 1;
    }
    return acc;
}, {});

将该对象映射到可排序数组中:

var assoc = counted.keys().map(function (fruit) {
    return [fruit, counted[fruit]];
});

排序数组:

assoc.sort(function (a, b) { return a[1] - b[1]; });

提取值:

var result = assoc.map(function (i) { return i[0]; });

您可以减少数组以删除重复项,然后使用自定义比较器进行排序:

var sorted = ['pear', 'apple', 'orange', 'apple', 'orange', 'apple'].reduce(function(result, item) {
    result.every(function(i) {
        return i != item;
    }) && result.push(item);
    return result;
}, []).sort(function(i1, i2) {
    return i1 > i2;
});
console.log(sorted);

使用linq.js非常容易(例如):

var array = ['pear', 'apple', 'orange', 'apple', 'orange', 'apple'];            
var res = Enumerable.From(array).GroupBy(function (x) { return x; }).Select(function (x) { return { key: x.Key(), count: x.Count() } }).OrderByDescending(function (x) { return x.count }).Select(function (x) { return x.key}).ToArray();

你可以试试lodash。你所需要做的就是groupsort,然后map,你就完成了。

var arr = ['pear', 'apple', 'orange', 'apple', 'orange', 'apple'];
document.body.innerHTML = _(arr).chain().groupBy()
  .sortBy(function(a) {
    return -a.length;   // <- Note: Remove the negation to sort in ascending order.
  }).map(function(a) {
    return a[0];
  }).value().join(', ');
<script src="https://cdn.rawgit.com/lodash/lodash/master/dist/lodash.js"></script>

试试这个:

var arr = ['pear', 'apple', 'orange', 'apple', 'orange', 'apple'];
var result = [];
var count = 0;
arr.sort();
for (var i = 0; i < arr.length; i++) {
  count++;
  if (arr[i] != arr[i + 1]) {
    result.push({
      "count": count,
      "value": arr[i]
    });
    count = 0;
  }
}
result.sort(function(a, b) {
  if (a.count < b.count) return 1;
  if (a.count > b.count) return -1;
  return 0;
});
console.log(result.map(function(item){return item.value}));

最新更新