2010-12-07 53 views
2

我正在尋找Linq RemoveFirst(Predicate<T> match),但只能找到RemoveAllLinq RemoveFirst等效

我知道我可以寫我自己的擴展方法,但不知道是否已經存在有不同的名稱,或者一個簡單的方法來達到同樣的效果等同功能。

+0

這不是LINQ;它已經在那裏.Net 2.0。 – SLaks 2010-12-07 16:58:27

+1

`RemoveAll`是`List `上的一個實例方法。它不是LINQ的一部分。 – Ani 2010-12-07 17:07:37

回答

6

像這樣:

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

如果沒有找到項,將引發異常。

請注意,這與LINQ無關,只能用List<T>完成。

0

此代碼實際上不「去除」從由於序列中的元件,如@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); 
    } 
0

由於沒有其他人提供了一個,這裏是我的擴展方法/ enumerable實現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; } 
     } 
    } 
}