获取数组中出现次数最多的项
Posted
技术标签:
【中文标题】获取数组中出现次数最多的项【英文标题】:Get the item that appears the most times in an array 【发布时间】:2011-04-16 14:02:33 【问题描述】:var store = ['1','2','2','3','4'];
我想知道2
在数组中出现的次数最多。我该怎么做呢?
【问题讨论】:
该数组是否总是排序的(就像在您的示例中一样)? 查看我的伪代码答案:***.com/questions/3774757/… 如果@Thilo 的问题的答案是肯定的,相同的元素将始终组合在一起。这允许您在将每个项目与前一个项目进行比较后遍历列表,并记录您遇到的相同元素的数量以及一路上遇到的最高运行次数。在循环结束时,您将得到答案。这将在线性时间内运行。如果@Thilo 的问题的答案是否定的,那么首先对列表进行排序,然后是上面的策略。 @Asaph:如果数组没有排序,codaddict的算法比排序好(如果你可以为频率计数器腾出额外的内存) @Thilo:是的。它好一点。但是排序并不是那么大的开销。 @codaddict 的算法在线性空间和线性时间中运行。我的建议在恒定空间和 O(n log n + n) 时间内运行,具体取决于排序算法。 【参考方案1】:我会这样做:
var store = ['1','2','2','3','4'];
var frequency = ; // array of frequency.
var max = 0; // holds the max frequency.
var result; // holds the max frequency element.
for(var v in store)
frequency[store[v]]=(frequency[store[v]] || 0)+1; // increment frequency.
if(frequency[store[v]] > max) // is this frequency > max so far ?
max = frequency[store[v]]; // update max.
result = store[v]; // update result.
【讨论】:
+1 - 非常好...但我会使用for
循环来阻止数组对象具有属性的极端情况:jsfiddle.net/9eJd3
我建议添加if (store.hasOwnProperty(v))
,以防有人决定修改 Object 或 Array 的原型,因为人们似乎有点热衷于在这里做这件事;P
@no - 这还不够好,因为store
可以拥有自己的属性,而这些属性不是数组的值。 (jsfiddle.net/vR5JK)。 for
循环可以解决问题,因为数组中的值之外的任何内容都不包含在 store[0]
到 store[store.length]
糟糕,for
循环我的意思是 for(var v=0; v < store.length; ++v)...
。
@Peter Ajtai - 我看到了你的例子,但这实际上是我所期望的行为......我希望数组对象的每个属性都计算在内,无论该属性是否也代表数组索引。这样它也可以用于常规对象。我想这取决于你想要什么行为。【参考方案2】:
以Array.prototype.forEach
为重点的解决方案,以及如果在更多项目之间共享最大计数时获得多个密钥的问题。
编辑:只有一个循环的提案。
var store = ['1', '2', '2', '3', '4', '5', '5'],
distribution = ,
max = 0,
result = [];
store.forEach(function (a)
distribution[a] = (distribution[a] || 0) + 1;
if (distribution[a] > max)
max = distribution[a];
result = [a];
return;
if (distribution[a] === max)
result.push(a);
);
console.log('max: ' + max);
console.log('key/s with max count: ' + JSON.stringify(result));
console.log(distribution);
【讨论】:
【参考方案3】:arr.sort();
var max=0,result,freq = 0;
for(var i=0; i < arr.length; i++)
if(arr[i]===arr[i+1])
freq++;
else
freq=0;
if(freq>max)
result = arr[i];
max = freq;
return result;
【讨论】:
由于有许多其他答案,添加解释为什么您的解决方案更可取可能会有所帮助。您可以通过单击“编辑”按钮添加说明... arr.sort() 是否总是对数组中不同类型的组进行正确排序? 是的@user2734550。 arr.sort() 能够正确排序数组中不同类型的组。但如果你正在处理单个数字和多个数字,你可能需要这样排序: arr.sort(function(a,b)return a- b;) 谢谢。我真的很喜欢你的解决方案!易于阅读且易于理解。也适用于字符串。 我喜欢您的解决方案,因为它使用了大多数 C 系列语言通用的基本 javascript 指令。【参考方案4】:制作直方图,找出直方图中最大数的key。
var hist = [];
for (var i = 0; i < store.length; i++)
var n = store[i];
if (hist[n] === undefined) hist[n] = 0;
else hist[n]++;
var best_count = hist[store[0]];
var best = store[0];
for (var i = 0; i < store.length; i++)
if (hist[store[i]] > best_count)
best_count = hist[store[i]];
best = store[i];
alert(best + ' occurs the most at ' + best_count + ' occurrences');
这假设要么没有关系,要么你不在乎选择了哪个。
【讨论】:
不过,如果数组已排序,则不需要。那么它可以是一个单遍操作。 附带说明,这称为分发模式。【参考方案5】:如果数组已排序,这应该可以:
function popular(array)
if (array.length == 0) return [null, 0];
var n = max = 1, maxNum = array[0], pv, cv;
for(var i = 0; i < array.length; i++, pv = array[i-1], cv = array[i])
if (pv == cv)
if (++n >= max)
max = n; maxNum = cv;
else n = 1;
return [maxNum, max];
;
popular([1,2,2,3,4,9,9,9,9,1,1])
[9, 4]
popular([1,2,2,3,4,9,9,9,9,1,1,10,10,10,10,10])
[10, 5]
【讨论】:
这些值不需要排序,只是分组。如果检查当前候选模式的频率if (pv != cv)
,则比较少。
@greybeard,arr.sort() 能很好地“分组”吗?我知道它对不同类型的排序不太好,但它是否正确分组?【参考方案6】:
当计数超过尚未计数的项目数时,此版本将退出查找。
它无需对数组进行排序即可工作。
Array.prototype.most= function()
var L= this.length, freq= [], unique= [],
tem, max= 1, index, count;
while(L>= max)
tem= this[--L];
if(unique.indexOf(tem)== -1)
unique.push(tem);
index= -1, count= 0;
while((index= this.indexOf(tem, index+1))!= -1)
++count;
if(count> max)
freq= [tem];
max= count;
else if(count== max) freq.push(tem);
return [freq, max];
//test
var A= ["apples","oranges","oranges","oranges","bananas",
"bananas","oranges","bananas"];
alert(A.most()) // [oranges,4]
A.push("bananas");
alert(A.most()) // [bananas,oranges,4]
【讨论】:
【参考方案7】:我用这种方法解决了寻找最常见的整数
function mostCommon(arr)
// finds the first most common integer, doesn't account for 2 equally common integers (a tie)
freq = [];
// set all frequency counts to 0
for(i = 0; i < arr[arr.length-1]; i++)
freq[i] = 0;
// use index in freq to represent the number, and the value at the index represent the frequency count
for(i = 0; i < arr.length; i++)
freq[arr[i]]++;
// find biggest number's index, that's the most frequent integer
mostCommon = freq[0];
for(i = 0; i < freq.length; i++)
if(freq[i] > mostCommon)
mostCommon = i;
return mostCommon;
【讨论】:
【参考方案8】:这是我的解决方案。
var max_frequent_elements = function(arr)
var a = [], b = [], prev;
arr.sort();
for ( var i = 0; i < arr.length; i++ )
if ( arr[i] !== prev )
a.push(arr[i]);
b.push(1);
else
b[b.length-1]++;
prev = arr[i];
var max = b[0]
for(var p=1;p<b.length;p++)
if(b[p]>max)max=b[p]
var indices = []
for(var q=0;q<a.length;q++)
if(b[q]==max)indices.push(a[q])
return indices;
;
【讨论】:
【参考方案9】:以上所有解决方案都是迭代的。
这是一个 ES6 功能无突变版本:
Array.prototype.mostRepresented = function()
const indexedElements = this.reduce((result, element) =>
return result.map(el =>
return
value: el.value,
count: el.count + (el.value === element ? 1 : 0),
;
).concat(result.some(el => el.value === element) ? [] : value: element, count: 1);
, []);
return (indexedElements.slice(1).reduce(
(result, indexedElement) => (indexedElement.count > result.count ? indexedElement : result),
indexedElements[0]) || ).value;
;
它可以在性能成为瓶颈的特定情况下进行优化,但它在处理任何类型的数组元素方面具有很大优势。
最后一行可以替换为:
return (indexedElements.maxBy(el => el.count) || ).value;
与:
Array.prototype.maxBy = function(fn)
return this.slice(1).reduce((result, element) => (fn(element) > fn(result) ? element : result), this[0]);
;
为了清楚
【讨论】:
【参考方案10】:如果数组包含字符串,试试这个解决方案
function GetMaxFrequency (array)
var store = array;
var frequency = []; // array of frequency.
var result; // holds the max frequency element.
for(var v in store)
var target = store[v];
var numOccurences = $.grep(store, function (elem)
return elem === target;
).length;
frequency.push(numOccurences);
maxValue = Math.max.apply(this, frequency);
result = store[$.inArray(maxValue,frequency)];
return result;
var store = ['ff','cc','cc','ff','ff','ff','ff','ff','ff','yahya','yahya','cc','yahya'];
alert(GetMaxFrequency(store));
【讨论】:
【参考方案11】:一个相当简短的解决方案。
function mostCommon(list)
var keyCounts = ;
var topCount = 0;
var topKey = ;
list.forEach(function(item, val)
keyCounts[item] = keyCounts[item] + 1 || 1;
if (keyCounts[item] > topCount)
topKey = item;
topCount = keyCounts[item];
);
return topKey;
document.write(mostCommon(['AA', 'AA', 'AB', 'AC']))
【讨论】:
【参考方案12】:此解决方案返回一个数组中出现次数最多的数字,以防多个数字出现在“最大”次。
function mode(numbers)
var counterObj = ;
var max = 0;
var result = [];
for(let num in numbers)
counterObj[numbers[num]] = (counterObj[numbers[num]] || 0) + 1;
if(counterObj[numbers[num]] >= max)
max = counterObj[numbers[num]];
for (let num in counterObj)
if(counterObj[num] == max)
result.push(parseInt(num));
return result;
【讨论】:
以上是关于获取数组中出现次数最多的项的主要内容,如果未能解决你的问题,请参考以下文章