2017-08-31 66 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

相关问题