首页 > 解决方案 > 我想使用 LINQ 获得最常见的值

问题描述

我正在尝试使用 C# 中的 LINQ 获取数组中最常见的值。

例如,

int[] input = {1, 1, 1, 3, 5, 5, 6, 6, 6, 7, 8, 8};

output = {1, 6}
int[] input = {1, 2, 2, 3 ,3, 3, 5}
output = {3}

请让我知道如何构建 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);

这个输出是 {1, 2, 3, 4, 5} 但我的预期输出 = {1, 2}

请仔细阅读问题并回答。

谢谢并恭祝安康。

标签: c#arrayslinq

解决方案


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

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" 

[编辑]

如果有人觉得这很有趣,我将 .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);
    }
}

(2) 修改调用OrderByDescending()以传递 a Comparer

.OrderByDescending(g => g.Key, new Comparer())

(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

对于 .net 5.0:

Comparing 3 with 1
Comparing 3 with 2
1, 6

如您所见,.net 5.0 得到了更好的优化。然而,对于 .net 框架(如 /u/mjwills 下文所述),使用MaxBy()扩展以避免必须使用可能会更高效OrderByDescending()- 但前提是检测表明排序导致性能问题。


推荐阅读