2012-09-06 70 views
0

我试图让内部的IEnumerable<T>获取项目

var collection = new[] { 1, 2, 3, 4, 5 }; 
var sequence = new[] { 2, 3 }; 

// IndexOf is an extension method. 
collection.IndexOf(sequence); // Should return 1 

我写了一个IndexOf扩展方法为这个项目的序列索引序列索引和除非有它工作正常在集合中的序列的第一个项目时,连续的一个以上:

// There are two items that are 2, consecutively in the collection, 
// which is the first item of the sequence. 
var collection = new[] { 1, 2, 2, 3, 4, 5 }; 
var sequence = new[] { 2, 3 }; 

collection.IndexOf(sequence); // Should return 2 but returns -1 

这里是IndexOf方法:

public static int IndexOf<T>(this IEnumerable<T> collection, 
    IEnumerable<T> sequence) 
{ 
    var comparer = EqualityComparer<T>.Default; 
    var counter = 0; 
    var index = 0; 
    var seqEnumerator = sequence.GetEnumerator(); 

    foreach (var item in collection) 
     if (seqEnumerator.MoveNext()) 
     { 
      if (!comparer.Equals(item, seqEnumerator.Current)) 
      { 
       seqEnumerator.Dispose(); 
       seqEnumerator = sequence.GetEnumerator(); 
       counter = 0; 

       // UPDATED AFTER MICHAEL'S ANSWER, 
       // IT WORKS WITH THIS ADDED PART: 
       seqEnumerator.MoveNext(); 
       if (comparer.Equals(item, seqEnumerator.Current)) 
        counter++; 
      } 
      else counter++; 
      index++; 
     } 
     else break; 

    var done = !seqEnumerator.MoveNext(); 
    seqEnumerator.Dispose(); 
    return done ? index - counter : -1; 
} 

我找不出如何解决这个问题。

+0

它应该返回2还是1(从零开始的索引)? –

+0

这非常有用? http://stackoverflow.com/questions/3561776/find-sequence-in-ienumerablet-using-linq – Ngm

+0

@Andre:它是从零开始的。在*集合*中找到的*序列*的第一项应该为零。 –

回答

2

当您在第一个位置遇到错误的符号时,重新启动序列迭代器,但不检查当前项是否匹配序列迭代器的开始,因此实际上永远不会将第2个序列与第2个序列进行比较。

2
public static int IndexOf<T>(this IEnumerable<T> collection, 
           IEnumerable<T> sequence) 
{ 
    var ccount = collection.Count(); 
    var scount = sequence.Count(); 

    if (scount > ccount) return -1; 

    if (collection.Take(scount).SequenceEqual(sequence)) return 0; 

    int index = Enumerable.Range(1, ccount - scount + 1) 
          .FirstOrDefault(i => collection.Skip(i).Take(scount).SequenceEqual(sequence)); 
    if (index == 0) return -1; 
    return index; 
} 
+0

我试图通过迭代集合来使其尽可能快。不过,重复序列是不可避免的。 –

+0

L.B,你可以在第一个if之前加上if(scount> ccount)return -1;''。有趣。 +1 – devgeezer

+0

@devgeezer补充。 –