【问题标题】:Efficient Linq Enumerable's 'Count() == 1' test高效的 Linq Enumerable 的 'Count() == 1' 测试
【发布时间】:2019-01-07 18:12:25
【问题描述】:

类似于question,但改写为 Linq:

您可以使用Enumerable<T>.Any() 来测试可枚举是否包含数据。但是,在不使用昂贵的计数操作的情况下,测试可枚举对象是否包含单个值(即Enumerable<T>.Count() == 1)或大于单个值(即Enumerable<T>.Count() > 1)的有效方法是什么?

【问题讨论】:

    标签: c# linq


    【解决方案1】:
    int constrainedCount = yourSequence.Take(2).Count();
    
    // if constrainedCount == 0 then the sequence is empty
    // if constrainedCount == 1 then the sequence contains a single element
    // if constrainedCount == 2 then the sequence has more than one element
    

    【讨论】:

    • 确保您不使用 yourSequence 数据本身,因为在某些情况下跳过或获取可能会丢失/使用数据。如果您只关心计数,那也没关系。
    【解决方案2】:

    一种方法是编写一个新的扩展方法

    public static bool IsSingle<T>(this IEnumerable<T> enumerable) {
      using (var enumerator = enumerable.GetEnumerator()) {
        if (!enumerator.MoveNext()) {
          return false;
        }
        return !enumerator.MoveNext();
      }
    }
    

    【讨论】:

    • @CodeArtist 一次测量毫无价值。您需要计算平均值和标准偏差。在我的机器上,差异是没有意义的。
    【解决方案3】:

    此代码采用 LukeH 的出色答案并将其包装为 IEnumerable 扩展名,以便您的代码可以处理 NoneOneMany 而不是 01 和 @ 987654327@.

    public enum Multiplicity
    {
        None,
        One,
        Many,
    }
    

    在静态类中,例如EnumerableExtensions:

    public static Multiplicity Multiplicity<TElement>(this IEnumerable<TElement> @this)
    {
        switch (@this.Take(2).Count())
        {
            case 0: return General.Multiplicity.None;
            case 1: return General.Multiplicity.One;
            case 2: return General.Multiplicity.Many;
            default: throw new Exception("WTF‽");
        }
    }
    

    【讨论】:

      【解决方案4】:

      另一种方式:

      bool containsMoreThanOneElement = yourSequence.Skip(1).Any();
      

      或者正好是 1 个元素:

      bool containsOneElement = yourSequence.Any() && !yourSequence.Skip(1).Any();
      

      【讨论】:

      • 这是我倾向于使用的,但 LukeH 的受限计数非常漂亮。
      • @Paul - 是的,它把seq.Any()seq.Skip(1).Any() 总结成了一个很好的声明。
      • 您需要将其与其他东西配对以查看计数是否为 1。不过,这涵盖了 > 1 的情况。
      【解决方案5】:

      高效Count() == n测试:

      public static bool CountIsEqualTo<T>(this IEnumerable<T> enumerable, int c) 
      {
          using (var enumerator = enumerable.GetEnumerator()) 
          {
              for(var i = 0; i < c ; i++)
                  if (!enumerator.MoveNext()) 
                      return false;
      
              return !enumerator.MoveNext();
          }
      }
      

      【讨论】:

        【解决方案6】:

        使用 linq to objects,如果有多个元素,SingleOrDefault 会抛出,所以如果你自己滚动,你可能是最好的。

        编辑:现在我看到了 LukeH 的回答,我不得不说我更喜欢它。希望我自己能想到!

        【讨论】:

        • Single() throws - SingleOrDefault() 将返回泛型类型的默认值(引用类型为 null)。
        • @David:不,如果有多个元素,SingleOrDefault 会抛出。如果没有元素,它只返回default(T)
        • @David,他对SingleOrDefault 的评论是正确的。 SingleSingleOrDefault 的区别不在于是否扔,而在于何时。
        【解决方案7】:
        bool hasTwo = yourSequence.ElementAtOrDefault(1) != default(T);
        

        ...如果类的值可以为空,这可能对我们有用。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-04-01
          • 2022-01-01
          • 2016-11-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-08-18
          相关资源
          最近更新 更多