我想使用 LINQ 获取最频繁的值

WSt*_*tar 3 c# linq arrays

我正在尝试使用 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}

请仔细阅读问题并回答。

感谢致敬。

Mat*_*son 9

只是为了添加过多的答案:

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()- 但前提是检测表明排序导致了性能问题。