【问题标题】:Simple LINQ question in C#C# 中的简单 LINQ 问题
【发布时间】:2011-03-23 01:39:36
【问题描述】:

我正在尝试使用LINQ 返回出现最大次数和出现次数的元素。

例如: 我有一个字符串数组:

string[] words = { "cherry", "apple", "blueberry", "cherry", "cherry", "blueberry" };

//...
Some LINQ statement here
//...

在此数组中,查询将返回 cherry 作为出现次数最多的元素,并返回 3 作为它出现的次数。如果有必要,我也愿意将它们分成两个查询(第一个查询获取cherry,第二个查询返回3 的计数。

【问题讨论】:

    标签: c# .net linq


    【解决方案1】:

    目前提出的解决方案是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<TSource>(
        this IEnumerable<TSource> source,
        Func<TSource, IComparable> 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;                
        }
    }
    

    【讨论】:

    • 如有必要,您也可以将Aggregate 替换为MaxBy,尽管MaxBy 更好更好:var max = words.GroupBy(x =&gt; x, (k, g) =&gt; new { Word = k, Count = g.Count() }).Aggregate((a, x) =&gt; (x.Count &gt; a.Count) ? x : a);
    • 伙计们! GroupBy 不是线性的。散列冲突的惩罚很小。我正在编造这个,但它类似于 O(n * log log n)
    • @Jakub Šturc:在最坏的情况下,排序可能会降级到O(n^2),具体取决于所使用的算法。但平均而言,它是O(n log n)GroupBy 通常是 O(n)
    【解决方案2】:
    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);
    

    【讨论】:

    【解决方案3】:

    首先想到的(意味着可能有更有效的方法)

    var item = words.GroupBy(x => x).OrderByDescending(x => x.Count()).First()
    //item.Key is "cherry", item.Count() is 3
    

    编辑:忘记了操作想要的名称计数

    【讨论】:

    【解决方案4】:
    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
    

    【讨论】:

    【解决方案5】:
    【解决方案6】:
    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 ()));
    

    【讨论】:

      【解决方案7】:

      一个更简单的 O(n) 解决方案:

      var groups = words.GroupBy(x => x);
      var max = groups.Max(x => x.Count());
      var top = groups.First(y => y.Count() == max).Key;
      

      【讨论】:

        【解决方案8】:

        这是一个非常快的 O(n) 解决方案,一行(!):

        s.GroupBy(x => x).Aggregate((IGrouping<string,string>)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);
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-02-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-02
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多