在Javascript中,我试图采取数字值的初始数组,并计算其中的元素。理想情况下,结果将是两个新数组,第一个数组指定每个唯一元素,第二个数组包含每个元素出现的次数。但是,我愿意听取关于输出格式的建议。

例如,如果初始数组是:

5, 5, 5, 2, 2, 2, 2, 2, 9, 4

然后将创建两个新数组。第一个将包含每个唯一元素的名称:

5, 2, 9, 4

第二个将包含该元素在初始数组中出现的次数:

3, 5, 1, 1

因为数字5在初始数组中出现了三次,数字2出现了五次,9和4都出现了一次。

我一直在寻找解决方案,但似乎没有一个可行,而且我自己尝试过的每件事最后都出奇地复杂。任何帮助都将不胜感激!

谢谢:)


当前回答

使用减法和波浪号(~)操作符的较短版本。

Const data = [2,2,2,2,2,2,4,5,5,5,9]; 函数频率(nums) { num返回。Reduce ((acc, curr) => { Acc [curr] = -~ Acc [curr]; 返回acc; }, {}); } console.log(频率(数据));

其他回答

返回一个可排序的数组:

let array = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4] let reducedArray = array.reduce( (acc, curr, _, arr) => { if (acc.length == 0) acc.push({item: curr, count: 1}) else if (acc.findIndex(f => f.item === curr ) === -1) acc.push({item: curr, count: 1}) else ++acc[acc.findIndex(f => f.item === curr)].count return acc }, []); console.log(reducedArray.sort((a,b) => b.count - a.count )) /* Output: [ { "item": 2, "count": 5 }, { "item": 5, "count": 3 }, { "item": 9, "count": 1 }, { "item": 4, "count": 1 } ] */

ES6版本应该更简单(另一个一行解决方案)

let arr = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4];
let acc = arr.reduce((acc, val) => acc.set(val, 1 + (acc.get(val) || 0)), new Map());

console.log(acc);
// output: Map { 5 => 3, 2 => 5, 9 => 1, 4 => 1 }

Map代替普通对象帮助我们区分不同类型的元素,否则所有计数都是基于字符串

你可以使用一个对象来保存结果:

Const arr = [5,5,5,2,2,2,2,2,2,2,2,9,4]; Const counts = {}; (const num of arr) { Counts [num] = Counts [num] ?计数[num] + 1: 1; } console.log(重要); Console.log(计数[5],计数[2],计数[9],计数[4]);

所以,现在你的counts对象可以告诉你一个特定数字的计数是多少:

console.log(counts[5]); // logs '3'

如果您想获取成员数组,只需使用keys()函数即可

keys(counts); // returns ["5", "2", "9", "4"]

编辑2020年:这是一个相当老的答案(9年)。扩展本机原型总是会引起讨论。尽管我认为程序员可以自由选择自己的编程风格,这里有一个(更现代的)方法来解决这个问题,而不需要扩展Array.prototype:

{ // create array with some pseudo random values (1 - 5) const arr = Array.from({length: 100}) .map( () => Math.floor(1 + Math.random() * 5) ); // frequencies using a reducer const arrFrequencies = arr.reduce((acc, value) => ({ ...acc, [value]: acc[value] + 1 || 1}), {} ) console.log(arrFrequencies); console.log(`Value 4 occurs ${arrFrequencies[4]} times in arrFrequencies`); // bonus: restore Array from frequencies const arrRestored = Object.entries(arrFrequencies) .reduce( (acc, [key, value]) => acc.concat(Array(value).fill(+key)), [] ); console.log(arrRestored.join()); } .as-console-wrapper { top: 0; max-height: 100% !important; }

旧的(2011年)答案是:你可以扩展Array。原型,像这样:

{ Array.prototype.frequencies = function() { var l = this.length, result = { all: [] }; while (l--) { result[this[l]] = result[this[l]] ? ++result[this[l]] : 1; } // all pairs (label, frequencies) to an array of arrays(2) for (var l in result) { if (result.hasOwnProperty(l) && l !== 'all') { result.all.push([l, result[l]]); } } return result; }; var freqs = [5, 5, 5, 2, 2, 2, 2, 2, 9, 4].frequencies(); console.log(`freqs[2]: ${freqs[2]}`); //=> 5 // or var freqs = '1,1,2,one,one,2,2,22,three,four,five,three,three,five' .split(',') .frequencies(); console.log(`freqs.three: ${freqs.three}`); //=> 3 // Alternatively you can utilize Array.map: Array.prototype.frequencies = function() { var freqs = { sum: 0 }; this.map(function(a) { if (!(a in this)) { this[a] = 1; } else { this[a] += 1; } this.sum += 1; return a; }, freqs); return freqs; } } .as-console-wrapper { top: 0; max-height: 100% !important; }

这个问题已经有8年的历史了,很多很多的答案都没有考虑到ES6及其众多的优势。

也许更重要的是,当我们创建额外的数组,创建数组的两倍或三倍副本,甚至将数组转换为对象时,考虑我们的代码对垃圾收集/内存管理的后果。对于小型应用来说,这些都是微不足道的观察结果,但如果规模化是一个长期目标,那么就要彻底考虑这些问题。

如果您只是需要一个特定数据类型的“计数器”,并且起点是一个数组(我假设您因此想要一个有序列表,并利用数组提供的许多属性和方法),那么您只需简单地遍历array1,并用array1中找到的这些值的值和出现次数填充array2。

就这么简单。

面向对象编程和面向对象设计的简单类SimpleCounter (ES6)的示例

class SimpleCounter { 

    constructor(rawList){ // input array type
        this.rawList = rawList;
        this.finalList = [];
    }

    mapValues(){ // returns a new array

        this.rawList.forEach(value => {
            this.finalList[value] ? this.finalList[value]++ : this.finalList[value] = 1;
        });

        this.rawList = null; // remove array1 for garbage collection

        return this.finalList;

    }

}

module.exports = SimpleCounter;