如果我有一个未排序的数组,它有多对相同的数字,我怎样才能找到最常用的数字?
int[] arr = new int[] {8, 6, 5, 2, 5, 9, 6, 9, 2, 3}; // unsorted array
// Array.Sort(arr); // I could sort the array
int mostCommon = arr.GroupBy(ii => ii) //Grouping same items
.OrderByDescending(abc => abc.Count()) //now getting frequency of a value
.Select(bcd => bcd.Key) //selecting key of the group
.FirstOrDefault(); //Finally, taking the most frequent value
在上面的例子中,我想得到2,但查询返回6.如果我在运行查询之前对数组进行排序,我会得到2,但我想知道是否有办法使用LINQ来从未排序的数组中获取最小的最常见值。 我对代码的快速执行不感兴趣。
答案 0 :(得分:3)
有两个2,两个6和两个9 - 假设你的意思是最低(2)应该在一个平局的情况下具有优先权,那么你只需要添加第二个排序,如下:
int mostCommon = arr.GroupBy(x => x)
.OrderByDescending(grp => grp.Count()) // First precedence = frequency
.ThenBy(grp => grp.Key) // Second precedence is lowest number first
.Select(bcd => bcd.Key)
.FirstOrDefault();
编辑,重新O(N)解决方案
这是一种方法,采用命令式方法,可以一次性完成数据。鉴于你已经在数组中指定了单个数字,我假设一个bin计数数组的范围是0-10(有利于将值初始化为零),但是如果你的范围更大,显然会调整。如果您的值很大并且可能很稀疏,那么您可能需要将Dictionary替换为数组。
var bins = new int[10]; // Adjust this to size / use Dictionary if sparse
var hiCount = 0;
var smallestMostCommon = int.MaxValue;
foreach(var a in arr)
{
var newCount = ++bins[a];
if (newCount > hiCount) // 1st Precedence : Frequency
{
hiCount = newCount;
smallestMostCommon = a;
}
else if (newCount == hiCount && a < smallestMostCommon) // 2nd : Lowest preferred
{
smallestMostCommon = a;
}
}
进一步的优化是可能的,我敢肯定,特别是在循环的任何一点,如果剩余的元素数量小于第一个和第二个最高的二进制数之间的差异,那么循环可以提前终止。 / p>
答案 1 :(得分:2)
您需要在Select
之前再次订购商品,因此FirstOrDefault
将返回最小的组密钥:
int smallestMostCommon = arr.GroupBy(ii => ii) //Grouping same items
.OrderByDescending(abc => abc.Count()) //now getting frequency of a value
.ThenBy(g => g.Key) // Make sure we get the smallest key first
.Select(bcd => bcd.Key) //selecting key of the group
.FirstOrDefault(); //Finally, taking the most frequent value
答案 2 :(得分:-1)
使用排序算法按数字顺序对数组中的值进行排序。搜索'冒泡排序'。我喜欢循环这个算法以确保准确性。然后对产品执行相同的排序以确定相似的值,并打印结果。