C#在字符串数组中查找最常见的字符串

C#在字符串数组中查找最常见的字符串,c#,arrays,string,linq,C#,Arrays,String,Linq,我有一个问题。有一根绳子 string [5] names = { "John", "Sam", "Harry", "Sam", "John" } 我需要找到数组中最常见的元素。我尝试使用: string MostCommon = names.GroupBy(v => v) .OrderByDescending(g => g.Count()) .First() .Key; 不幸的是,它只找到一个元素,例如,MostCommon=John,在这种情况下,我不

我有一个问题。有一根绳子

string [5] names = { "John", "Sam", "Harry", "Sam", "John" }
我需要找到数组中最常见的元素。我尝试使用:

string MostCommon = names.GroupBy(v => v)
    .OrderByDescending(g => g.Count())
    .First()
    .Key;

不幸的是,它只找到一个元素,例如,
MostCommon=John
,在这种情况下,我不仅需要
John
,还需要
Sam
。我怎么能这么做?在这种情况下可能不需要LINQ?

First
显然只会选择序列的第一个元素。但是,您需要所有组的数量相等。因此,请选择每个组的名称和编号,然后再订购。最后选择与第一组计数相同的所有组

var groups = names.GroupBy(x => x)
    .Select(x => new { x.Key, Count = x.Count() })
    .OrderByDescending(x => x.Count);
int max = groups.First().Count;
var mostCommons = groups.Where(x => x.Count == max);
编辑:您还可以在最后一条语句中使用而不是
Where
,这将避免对
-列表中的最后一个元素进行不必要的比较,并在发现第一个组的元素少于第一个组时立即停止:

var mostCommons = groups.TakeWhile(x => x.Count == groups.First().Count);

根据您找到的最常用名称的计数,将您的第一个LINQ与另一个类似的LINQ组合起来

string MostCommon = names.GroupBy(v => v)
    .OrderByDescending(g => g.Count())
    .First();

int count = names.Where(x => x == MostCommon).Count();

var mostCommonList = names.GroupBy(v => v)
    .Where(g => g.Count() == count);

这可以按如下方式进行-

 var nameGroup = names.GroupBy(x => x);
 var maxCount = nameGroup.Max(g => g.Count());
 var mostCommons = nameGroup.Where(x => x.Count() == maxCount).Select(x => x.Key).ToArray();
//带字典
//如果你想采访大公司,这会更有用,否则就使用
Linq选项,短而方便
公共静态int MaxOccurrenceOfWord(字符串[]个字)
{
var counts=新字典();
int=0;
foreach(单词中的var单词)
{
整数计数;
counts.TryGetValue(字,超出计数);
计数++;
//如果条目存在,则自动替换该条目;
//无需使用“包含”
计数[字]=计数;
}
字符串mostCommonWord=null;
foreach(计数中的var对)
{
如果(pair.Value>出现次数)
{
出现次数=配对值;
mostCommonWord=pair.Key;
}
}
WriteLine(“最常见的数字是{0},它出现了{1}次”,
最常见的词、事件);
返回事件;
}

.First()
是您的问题。取下
.First()
,您将得到多个结果,但您不知道单个LINQ语句的具体计数。No的可能重复,该重复是OP想要避免的,仅选择第一个最大值。它不处理多个成员可能具有最大计数的OP的情况。由于最后一行上不存在
.Key
属性(加上分配
mostCommonList
中的附加
=
),因此无法编译。不能假定只有一个“最常见的名称”,因此结果需要是
IEnumerable
,而不是
string
。因此,
.Key
需要删除(或者用
.Select(v=>v)
替换,效果不太好)。@BACON有太多的坏拷贝/pastas,谢谢你叫我出来。我修复了
=
并删除了
.Key
语句。我认为如果没有
,答案应该可以。选择()
作为
。其中
将返回一个可枚举项。这是一种非常低效的方法,它会多次执行
查询(涉及分组和排序)。至少将
groups.First().Count
放入上一个查询之外的变量中,以使
groups
查询“仅”执行两次。尽管如此,它仍然比Amit-Hasan方法更糟糕(并且不计算可能的非LINQ解决方案),但至少可以被认为不是那么糟糕。这是关于
TakeWhile
优于
Where
的优点的一个非常好的观点。为了将来读者的利益,我认为您应该考虑使用<代码> Tuffer-<代码>添加代码片段,甚至可能删除<<代码> 代码,完全是因为<代码> Tuffer-<代码>是更好的选择。然而,我怀疑是否有一种方法可以避免执行两次group语句,即使在您引用的答案中,
namegroup
也会重复两次。我们可以使用
ToList
强制立即评估,但到目前为止,两种解决方案的性能应该相似。我使用非LINQ方法对此进行了测试,该方法还需要对原始序列进行两次迭代。@Himbrombere正确。关键是不要执行N次:)使用
Max
+
的方法更好,因为即使有2次通过,它也是O(N)。而
OrderByDescending
+
First
是O(N*lg(N)),如您所知
GroupBy
在这两种情况下,操作都是O(N),所以我不计算它。
//With Dictionary
//This is more useful if you are looking to interview big companies otherwise use the 
 Linq option which is short and handy

public static int MaxOccurrenceOfWord(string[] words)
    {
        var counts = new Dictionary<string, int>();
        int occurrences = 0;
        foreach (var word in words)
        {
            int count;
            counts.TryGetValue(word, out count);
            count++;
             //Automatically replaces the entry if it exists;
            //no need to use 'Contains'
            counts[word] = count;
        }

        string mostCommonWord = null;
        foreach (var pair in counts)
        {
            if (pair.Value > occurrences)
            {
                occurrences = pair.Value;
                mostCommonWord = pair.Key;
            }
        }
        Console.WriteLine("The most common number is {0} and it appears {1} times",
            mostCommonWord, occurrences);

        return occurrences;

    }