2010-08-25 7 views

Antwort

23

dachte es einfach aus mir ...

Die IEnumerable<T>.Where() Methode, um eine Überlastung hat, die den Index des aktuellen Elements nimmt - genau das, was der Arzt verordnet.

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

Dies würde zurückkehren

{1, 3, 5} 

Update: Um sowohl meinen Anwendungsfall und Dan Tao Vorschlag zu decken, wollen sie festlegen, was auch das erste sollte zurück Element sein:

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); 

... würde zurückgeben

{2, 4} 
+2

Zum ersten Mal habe ich eine wirklich solide Verwendung für den Index in einem Kollektionsprädikat gesehen, Bravo, hätte ich mir das nicht ausgedacht. –

+0

Sie könnten eine Erweiterungsmethode definieren, die das zurückgibt.Wohin (...), um dies in Ihrer App selbst deutlicher zu machen. – Douglas

+5

Ich könnte vorschlagen, 'idx + 1' zu verwenden, um der Beschreibung von" jedem Nth Element "zu entsprechen; zumindest für mich deutet dies darauf hin, dass das erste zurückgegebene Element das N-te Element sein sollte. Jedes zweite Element in '{1,2,3,4,5}' - zu * me * - bedeutet '{2,4}' (Ihr Code gibt '{1,3,5}' zurück). Vielleicht ist das jedoch subjektiv. –

8

Zur Umsetzung 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); 
} 

Verbrauch:

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

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

Sie könnten auch das Array überspringen und 'Enumerable.Range (1,10)' verwenden. –

+2

@Anthony: Es ist nur ein Beispiel, zum sofortigen Verständnis gedacht. Ich weiß, dass einige Entwickler "Enumerable.Range" nachschlagen müssten. –

0

Während nicht LINQ können Sie auch eine Erweiterungsmethode mit yield erstellen.

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

Wrap das in einem 'using'! ('IEnumerable' erbt' IDisposable'.) –

+0

@Dan: Du meinst IEnumerator. Wieso habe ich das vorher nie bemerkt?

+0

Ja, ich meinte 'IEnumerator'. Hoppla! (Aus irgendeinem Grund gebe ich immer einen ein, wenn ich den anderen eingeben möchte. Muss Muskelgedächtnis sein.) –

Verwandte Themen