我正在尝试使用 C# 中的 LINQ 获取数组中最常见的值。
例如,
int[] input = {1, 1, 1, 3, 5, 5, 6, 6, 6, 7, 8, 8};
output = {1, 6}
Run Code Online (Sandbox Code Playgroud)
int[] input = {1, 2, 2, 3 ,3, 3, 5}
output = {3}
Run Code Online (Sandbox Code Playgroud)
请让我知道如何构建 LINQ。
请仔细阅读。这是使用 LINQ 选择最常见值的不同问题
我必须只选择最常见的值。下面的代码类似,但我不能使用 Take(5),因为我不知道结果的数量。
int[] nums = new[] { 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7 };
IEnumerable<int> top5 = nums
.GroupBy(i => i)
.OrderByDescending(g => g.Count())
.Take(5)
.Select(g => g.Key);
Run Code Online (Sandbox Code Playgroud)
这个输出是 {1, 2, 3, 4, 5} 但我的预期输出 = {1, 2}
请仔细阅读问题并回答。
感谢致敬。
只是为了添加过多的答案:
int[] input = { 1, 1, 1, 3, 5, 5, 6, 6, 6, 7, 8, 8 };
var result = input
.GroupBy(i => i)
.GroupBy(g => g.Count())
.OrderByDescending(g => g.Key)
.First()
.Select(g => g.Key)
.ToArray();
Console.WriteLine(string.Join(", ", result)); // Prints "1, 6"
Run Code Online (Sandbox Code Playgroud)
[编辑]
如果有人觉得这很有趣,我比较了 .net 4.8 和 .net 5.0 之间的上述性能,如下所示:
(1) 添加了一个Comparer类来检测比较次数:
class Comparer : IComparer<int>
{
public int Compare(int x, int y)
{
Console.WriteLine($"Comparing {x} with {y}");
return x.CompareTo(y);
}
}
Run Code Online (Sandbox Code Playgroud)
(2) 修改调用OrderByDescending()以传递Comparer:
.OrderByDescending(g => g.Key, new Comparer())
Run Code Online (Sandbox Code Playgroud)
(3) 将我的测试控制台应用程序多定位到“net48”和“net5.0”。
进行这些更改后,输出如下:
对于.net 4.8:
Comparing 1 with 3
Comparing 1 with 1
Comparing 1 with 2
Comparing 3 with 3
Comparing 3 with 2
Comparing 3 with 3
1, 6
Run Code Online (Sandbox Code Playgroud)
对于.net 5.0:
Comparing 3 with 1
Comparing 3 with 2
1, 6
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,.net 5.0 优化得更好。MaxBy()然而,对于 .net Framework(如下面 /u/mjwills 提到的),使用扩展以避免必须使用可能会更具性能OrderByDescending()- 但前提是检测表明排序导致了性能问题。