C#中简单的LINQ问题
我试图使用LINQ
返回一个发生最大次数的元素及其发生的次数。
例如:我有一个字符串数组:
string[] words = { "cherry", "apple", "blueberry", "cherry", "cherry", "blueberry" }; //... Some LINQ statement here //...
在此数组中,查询将返回cherry
作为最大发生元素,并返回3
作为其发生的次数。 如果有必要,我也愿意将它们分成两个查询( 即,第一个查询获取cherry
,第二个返回3
计数。
var topWordGroup = words.GroupBy(word => word).OrderByDescending(group => group.Count()).FirstOrDefault(); // topWordGroup might be a null! string topWord = topWordGroup.Key; int topWordCount = topWordGroup.Count;
如果我们不喜欢O(N log N)
:
var topWordGroup = words.GroupBy(word => word).Aggregate((current, acc) => current.Count() < acc.Count() ? acc : current);
到目前为止提出的解决方案是O(n log n)
。 这是一个O(n)
解决方案:
var max = words.GroupBy(w => w) .Select(g => new { Word = g.Key, Count = g.Count() }) .MaxBy(g => g.Count); Console.WriteLine( "The most frequent word is {0}, and its frequency is {1}.", max.Word, max.Count );
这需要MaxBy
的定义。 这是一个:
public static TSource MaxBy( this IEnumerable source, Func projectionToComparable ) { using (var e = source.GetEnumerator()) { if (!e.MoveNext()) { throw new InvalidOperationException("Sequence is empty."); } TSource max = e.Current; IComparable maxProjection = projectionToComparable(e.Current); while (e.MoveNext()) { IComparable currentProjection = projectionToComparable(e.Current); if (currentProjection.CompareTo(maxProjection) > 0) { max = e.Current; maxProjection = currentProjection; } } return max; } }
首先想到的是(意味着可能有更有效的方式)
var item = words.GroupBy(x => x).OrderByDescending(x => x.Count()).First() //item.Key is "cherry", item.Count() is 3
编辑 :忘了操作想要的名字和计数
string[] words = { "cherry", "apple", "blueberry", "cherry", "cherry", "blueberry" }; var topWordAndCount=words .GroupBy(w=>w) .OrderByDescending(g=>g.Count()) .Select(g=>new {Word=g.Key,Count=g.Count()}) .FirstOrDefault(); //if(topWordAndCount!=null) //{ // topWordAndCount.Word // topWordAndCount.Count
试试这个:
将包含top,count,group和order的SQL转换为LINQ(2个实体)
string[] words = { "cherry", "apple", "blueberry", "cherry", "cherry", "blueberry" }; var r = words.GroupBy (x => x) .OrderByDescending (g => g.Count ()) .FirstOrDefault (); Console.WriteLine (String.Format ("The element {0} occurs {1} times.", r.Key, r.Count ()));
一个更简单的O(n)解决方案:
var groups = words.GroupBy(x => x); var max = groups.Max(x => x.Count()); var top = groups.First(y => y.Count() == max).Key;
这是一行中非常快速的O(n)解决方案(!):
s.GroupBy(x => x).Aggregate((IGrouping)null, (x, y) => (x != null && y != null && x.Count() >= y.Count()) || y == null ? x : y, x => x);
或这个:
s.GroupBy(x => x).Select(x => new { Key = x.Key, Count = x.Count() }).Aggregate(new { Key = "", Count = 0 }, (x, y) => x.Count >= y.Count ? x : y, x => x);