2017-08-31 68 views
2

我最近遇到了一個場景,我需要檢查一個IEnumerable<T>是否以一些IEnumerable<T>前綴開頭。我搜索並沒有找到一個現有的StackOverflow答案,所以我決定在下面的答案中提供我自己的解決方案。如何在.NET中檢查IEnumerable <T>是否以另一個IEnumerable <T>開頭?

+0

請不要使用StackOverflow的您的個人博客。提出一個問題,但不要像這樣一次提出問題並回答問題。 – Enigmativity

+0

@Enigmativity我不認爲回答我自己的問題有什麼問題。這是我遇到的一個真正的問題,其他人也可能遇到。我將與世界其他地方分享我的知識,以便其他開發人員可以快速Google並找到解決方案,而不是浪費時間編寫自己的實現。 –

+0

我記得當時看到它被人折磨的地方,但我現在找不到那個參考。那麼快樂的日子。去吧。 – Enigmativity

回答

1

這是一種LINQ風格的擴展方法,我通過允許您傳入自定義相等比較器來靈活地實現我的實現:例如,如果您希望new[] { "SOME", "IMPORTANT", "WORDS" }.StartsWith(new[] { "some", "important" })爲真,則可以在prefix參數後面添加StringComparer.OrdinalIgnoreCase

public static bool StartsWith<T>(this IEnumerable<T> source, IEnumerable<T> prefix, IEqualityComparer<T> comparer = null) 
{ 
    if (source == null) 
    { 
     throw new ArgumentNullException(nameof(source)); 
    } 
    if (prefix == null) 
    { 
     throw new ArgumentNullException(nameof(prefix)); 
    } 

    comparer = comparer ?? EqualityComparer<T>.Default; 

    using (var sourceEnumerator = source.GetEnumerator()) 
    using (var prefixEnumerator = prefix.GetEnumerator()) 
    { 
     while (true) 
     { 
      if (!sourceEnumerator.MoveNext()) 
      { 
       return !prefixEnumerator.MoveNext(); 
      } 

      if (!prefixEnumerator.MoveNext()) 
      { 
       return true; 
      } 

      if (!comparer.Equals(sourceEnumerator.Current, prefixEnumerator.Current)) 
      { 
       return false; 
      } 
     } 
    } 
} 
6

你的擴展是好的,但你可以使用已有的Enumerable.Zip + All

var longerSeq = new[] { "SOME", "IMPORTANT", "WORDS" }; 
var shorterSeq = new[] { "some", "important" }; 

bool startsWithCaseInsensitive = longerSeq 
    .Zip(shorterSeq, (l, s) => string.Equals(l, s, StringComparison.OrdinalIgnoreCase)) 
    .All(b => b); // are all bools true? Returns false on first false 

Documentation

的方法合併第一序列的每個元素與元素 在第二個序列中具有相同的索引。 如果序列不 沒有相同數量的元素,方法合併序列 直到它到達其中一個結束

由於Zip使用延遲執行它不會評估所有,如果第一已產生了false

+1

雖然這不等同於OP解決方案。如果「前綴」序列長於「源」序列,​​'StartsWith'應該返回'false'。哪個'Zip'實現無法區分。 –

0
bool result = longerList.Take(shorterList.Count).SequenceEqual(shorterList); 

你也可以添加比較方法SequenceEqual:

bool result = longerList.Take(shorterList.Count).SequenceEqual(shorterList, new MyComparer<string>); 

參見:Enumerable.SequenceEqual Method

相關問題