按频率对 Javascript 数组进行排序,然后过滤重复项

问题描述 投票:0回答:8

采用 JavaScript 数组、按值的频率排序,然后过滤唯一值的优雅方法是什么?

那么,

["apples", "oranges", "oranges", "oranges", "bananas", "bananas", "oranges"]

成为

["oranges, "bananas", "apples"]

javascript arrays sorting
8个回答
38
投票

首先计算每个项目的频率。

{
    apples: 1,
    oranges: 4,
    bananas: 2
}

然后从此频率对象创建一个数组,这也将删除重复项。

["apples", "oranges", "bananas"]

现在使用我们之前创建的频率图按降序排列该数组。

function compareFrequency(a, b) {
    return frequency[b] - frequency[a];
}

array.sort(compareFrequency);

这是整个源代码(使用 ECMA 5 中新引入的数组函数)并结合了重复数据删除和频率图生成步骤,

function sortByFrequency(array) {
    var frequency = {};

    array.forEach(function(value) { frequency[value] = 0; });

    var uniques = array.filter(function(value) {
        return ++frequency[value] == 1;
    });

    return uniques.sort(function(a, b) {
        return frequency[b] - frequency[a];
    });
}

与上面使用常规数组迭代相同。

function sortByFrequencyAndRemoveDuplicates(array) {
    var frequency = {}, value;

    // compute frequencies of each value
    for(var i = 0; i < array.length; i++) {
        value = array[i];
        if(value in frequency) {
            frequency[value]++;
        }
        else {
            frequency[value] = 1;
        }
    }

    // make array from the frequency object to de-duplicate
    var uniques = [];
    for(value in frequency) {
        uniques.push(value);
    }

    // sort the uniques array in descending order by frequency
    function compareFrequency(a, b) {
        return frequency[b] - frequency[a];
    }

    return uniques.sort(compareFrequency);
}

6
投票

// 返回最频繁到最不频繁

Array.prototype.byCount= function(){
    var itm, a= [], L= this.length, o= {};
    for(var i= 0; i<L; i++){
        itm= this[i];
        if(!itm) continue;
        if(o[itm]== undefined) o[itm]= 1;
        else ++o[itm];
    }
    for(var p in o) a[a.length]= p;
    return a.sort(function(a, b){
        return o[b]-o[a];
    });
}

//测试

var A= ["apples","oranges","oranges","oranges","bananas","bananas","oranges"];
A.byCount()

/* 返回值:(数组) 橙子、香蕉、苹果 */


3
投票

我实际上正在同时研究这个问题 - 我想出的解决方案与 Anurag 的解决方案几乎相同。

但是我认为这可能值得分享,因为我计算出现频率的方式略有不同,使用三元运算符并检查该值是否已以稍微不同的方式计算。

function sortByFrequencyAndFilter(myArray)
{
    var newArray = [];
    var freq = {};

    //Count Frequency of Occurances
    var i=myArray.length-1;
    for (var i;i>-1;i--)
    {
        var value = myArray[i];
        freq[value]==null?freq[value]=1:freq[value]++;
    }

    //Create Array of Filtered Values
    for (var value in freq)
    {
        newArray.push(value);
    }

    //Define Sort Function and Return Sorted Results
    function compareFreq(a,b)
    {
        return freq[b]-freq[a];
    }

    return newArray.sort(compareFreq);
}

1
投票

基本策略:

创建一个对象用作哈希表,以跟踪要排序的数组中每个项目的频率。

创建一个包含项目、频率对的新数组。

按频率降序排列此数组。

从该数组中提取项目。

代码:

function descendingUniqueSort(toBeSorted) {
    var hash = new Object();
    toBeSorted.forEach(function (element, index, array) { 
                           if (hash[element] == undefined) {
                               hash[element] = 1;
                           }
                           else {
                               hash[element] +=1;
                           }});
    var itemCounts = new Array();
    for (var key in hash) {
       var itemCount = new Object();
       itemCount.key = key;
       itemCount.count = hash[key];
       itemCounts.push(itemCount);
    }
    itemCounts.sort(function(a,b) { if(a.count<b.count) return 1; 
        else if (a.count>b.count) return -1; else return 0;});

    return itemCounts.map(function(itemCount) { return itemCount.key; });
 }

1
投票
var arr = ["apples", "oranges", "oranges", "oranges", "bananas", "bananas", "oranges"].sort();
var freq = {};
for (var s in arr) freq[s] = freq[s] ? freq[s] + 1 : 0;
arr.sort(function(a, b) { return freq[a] > freq[b] ? -1 : 1; });
for (var i = arr.length - 1; i > 0; i--) if (arr[i] == arr[i - 1]) arr.splice(i,1);
alert(arr.join(","));

1
投票

第一步计算

{
    oranges: 4,
    bananas: 2,
    apples: 1
}

您可以使用 underscroe.js 的 countBy 函数

var all=["apples", "oranges", "oranges", "oranges", "bananas", "bananas", "oranges"];
var frequency=_.countBy(all,function(each){return each});

所以

frequency
对象将包含所有唯一值的频率,您只需调用
_.uniq(all)
即可获得唯一列表,并通过下划线的
_.sortBy
方法对该唯一列表进行排序并使用您的
frequency
对象可以用

_.sortBy(_.uniq(all),function(frequencyKey){return -frequency[frequencyKey]});

-ve
符号用于根据您的要求按频率值降序对列表进行排序。

你可以查看http://underscorejs.org/的文档,通过你自己的技巧进一步优化:)


1
投票

使用

reduce
:

创建数组元素的计数器
arr.reduce(
  (counter, key) => {counter[key] = 1 + counter[key] || 1; return counter}, 
  {}
);

使用

sort
Object.entries
对计数器对象进行排序,最后仅显示键。

const arr = ["apples", "oranges", "oranges", "oranges",
  "bananas", "bananas", "oranges"
];

// create a counter object on array
let counter = arr.reduce(
  (counter, key) => {
    counter[key] = 1 + counter[key] || 1;
    return counter
  }, {});
console.log(counter);
// {"apples": 1, "oranges": 4, "bananas": 2}

// sort counter by values (compare position 1 entries)
// the result is an array
let sorted_counter = Object.entries(counter).sort((a, b) => b[1] - a[1]);
console.log(sorted_counter);
// [["oranges", 4], ["bananas", 2], ["apples", 1]]

// show only keys of the sorted array
console.log(sorted_counter.map(x => x[0]));
// ["oranges", "bananas", "apples"]


1
投票

让我输入一个最少的代码来获取 ES6 中的唯一值(和频率)。

var arr = ["apples", "oranges", "oranges", "oranges", "bananas", "bananas", "oranges"];
console.log([...new Set(arr)])
console.log([...new Set(arr)].map(fruit=>({[fruit]:arr.filter(v=>(v===fruit)).length})))

它也适用于对象数组来聚合一些属性。

var arr = [{"fruit":"apples"}, {"fruit":"oranges"}, {"fruit":"oranges"}, {"fruit":"oranges"}, {"fruit":"bananas"}, {"fruit":"bananas"}, {"fruit":"oranges"}];
console.log(arr.reduce((x,y)=>{if(x[y.fruit]) {x[y.fruit]++;return x;} else {var z={};z[y.fruit]=1;return Object.assign(x,z);}},{}))

© www.soinside.com 2019 - 2024. All rights reserved.