2010-08-25 30 views

回答

23

就想通了自己...

IEnumerable<T>.Where()方法有一個重載,是以當前元素的索引 - 醫生給你開。

(new []{1,2,3,4,5}).Where((elem, idx) => idx % 2 == 0); 

這將返回

{1, 3, 5} 

更新:爲了掩飾我的兩個用例和丹道的建議,我們也可以指定返回的第一個元素應該是什麼:

var firstIdx = 1; 
var takeEvery = 2; 
var list = new []{1,2,3,4,5}; 

var newList = list 
    .Skip(firstIdx) 
    .Where((elem, idx) => idx % takeEvery == 0); 

...將返回

{2, 4} 
+2

我第一次看到索引在集合謂詞bravo中非常穩定的用法,我不會想到這件事。 – 2010-08-25 16:21:56

+0

你可以定義一個擴展方法,它返回this.Where(...)使你的應用程序本身更清晰。 – Douglas 2010-08-25 16:22:27

+5

我可能會建議使用'idx + 1'來匹配「每N個元素」的描述;至少對我來說,這表明返回的第一個元素應該是第N個元素。因此'{1,2,3,4,5}' - to * me * - 中的每個第二個元素表示'{2,4}'(您的代碼返回'{1,3,5}')。不過,也許這是主觀的。 – 2010-08-25 16:23:13

8

要實現Cristi's suggestion

public static IEnumerable<T> Sample<T>(this IEnumerable<T> source, int interval) 
{ 
    // null check, out of range check go here 

    return source.Where((value, index) => (index + 1) % interval == 0); 
} 

用法:

var upToTen = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 

var evens = upToTen.Sample(2); 
var multiplesOfThree = upToTen.Sample(3); 
+0

你也可以跳過數組並使用'Enumerable.Range(1,10)'。 – 2010-08-25 17:34:18

+2

@Anthony:這只是一個例子,用於立即理解。我知道一些開發人員必須查找'Enumerable.Range'。 – 2010-08-25 18:27:31

0

雖然不是LINQ你還可以與yield創建一個擴展方法。

public static IEnumerable<T> EverySecondObject<T>(this IEnumerable<T> list) 
{ 
    using (var enumerator = list.GetEnumerator()) 
    { 
     while (true) 
     { 
      if (!enumerator.MoveNext()) 
       yield break; 
      if (enumerator.MoveNext()) 
       yield return enumerator.Current; 
      else 
       yield break; 
     } 
    } 
} 
+2

用''使用'把它包起來! ('IEnumerable'繼承'IDisposable'。) – 2010-08-25 19:01:03

+0

@Dan:你的意思是IEnumerator。我以前從未意識到這一點? <挖掘一些舊代碼/> – 2010-08-25 19:19:40

+0

是的,我的意思是'IEnumerator'。哎呦! (出於某種原因,我總是輸入其中一個,意思是輸入另一個。必須是肌肉記憶。) – 2010-08-25 19:26:59

相關問題