【问题标题】:Linq RemoveFirst equivalentLinq RemoveFirst 等效项
【发布时间】:2010-12-07 16:56:50
【问题描述】:

我正在寻找 Linq RemoveFirst(Predicate<T> match),但只能找到 RemoveAll

我知道我可以编写自己的扩展方法,但想知道是否已经存在具有不同名称的等效函数,或者是实现相同结果的简单方法。

【问题讨论】:

  • 那不是 LINQ;自 .Net 2.0 以来就一直存在。
  • RemoveAllList<T> 上的实例方法。它不是 LINQ 的一部分。
  • 这与IEnumerable<T>无关,是只读接口。

标签: linq lambda ienumerable


【解决方案1】:

像这样:

list.RemoveAt(list.FindIndex(x => thingy));

如果没有找到项目,则会抛出异常。

请注意,这与 LINQ 无关,只能使用 List<T> 完成。

【讨论】:

    【解决方案2】:

    此代码实际上并没有从序列中“删除”元素,因为@SLaks 指出 linq 序列是只读的,但它确实跳过了第一次出现的符合条件的元素。它不是特别有效,因为每个列表操作都将遍历列表。它合理地表达了您要完成的工作。根据您希望列表中有多少项目,这对您来说可能是合理的。

      IEnumerable<int> x = Enumerable.Range(0, 20);
      var y = x.TakeWhile(xx => xx < 10).Concat(x.SkipWhile(xx => xx < 10).Skip(1));
    
      //Will write 0 1 2 ... 19, skipping 10
      foreach(int a in y)
      {
        System.Diagnostics.Debug.WriteLine(a);
      }
    

    【讨论】:

      【解决方案3】:

      由于没有其他人提供,这是我的扩展方法/可枚举实现 RemoveFirst(谓词匹配)。诀窍基本上是您需要定义自己的 IEnumerable 来正确跟踪状态——我找不到简单的解决方法。

      您可以在.NET Fiddle here 中试用。

      public static IEnumerable<T> RemoveFirst<T>(this IEnumerable<T> list, Func<T, bool> predicate)
      {
          return new RemoveFirstEnumerable<T>(list, predicate);
      }
      
      public static IEnumerable<T> RemoveFirst<T>(this IEnumerable<T> list, T item)
      {
          return RemoveFirst(list, x => Object.Equals(x, item));
      }
      private class RemoveFirstEnumerable<T> : IEnumerable<T>
      {
          IEnumerable<T> m_Source;
          Func<T, bool> m_Predicate;
      
          public RemoveFirstEnumerable(IEnumerable<T> source, Func<T, bool> predicate)
          {
              m_Source = source;
              m_Predicate = predicate;
          }
      
          public IEnumerator<T> GetEnumerator()
          {
              return new RemoveFirstEnumerator(m_Source, m_Predicate);
          }
      
          IEnumerator IEnumerable.GetEnumerator()
          {
              return new RemoveFirstEnumerator(m_Source, m_Predicate);
          }
      
          private class RemoveFirstEnumerator : IEnumerator<T>
          {
              IEnumerator<T> m_Enumerator;
              Func<T, bool> m_Predicate;
              bool m_RemovedOnce = false;
              public RemoveFirstEnumerator(IEnumerable<T> source, Func<T, bool> predicate)
              {
                  m_Enumerator = source.Where(WherePredicate).GetEnumerator();
                  m_Predicate = predicate;
              }
      
              bool WherePredicate(T current)
              {
                  // terse version:
                  return m_RemovedOnce || !(m_RemovedOnce = m_Predicate(current));
      
                  // Long version
                  //if (m_RemovedOnce)
                  //{
                  //    return true;
                  //}
                  //else
                  //{
                  //    m_RemovedOnce = Object.Equals(x, item);
                  //    return !m_RemovedOnce;
                  //}
              }
      
              public T Current
              {
                  get { return m_Enumerator.Current; }
              }
      
              public bool MoveNext()
              {
                  return m_Enumerator.MoveNext();
              }
      
      
              public void Reset()
              {
                  m_Enumerator.Reset();
              }
      
              public void Dispose()
              {
                  m_Enumerator.Dispose();
              }
      
              object IEnumerator.Current
              {
                  get { return m_Enumerator.Current; }
              }
          }
      }
      

      【讨论】:

        【解决方案4】:

        确实,经典 List 有一个 RemoveAll(match),但没有一个 RemoveFirst(match)。扩展方法可以是

        public static class ListExtensions
        {
            public static void RemoveFirst<T>(this List<T> list, Predicate<T> match)
            {
                list.RemoveAt(list.FindIndex(match));
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-05-14
          • 2012-08-23
          • 1970-01-01
          相关资源
          最近更新 更多