2012-04-20 13 views
14

Linqを使用しています。私はTakeの "反対"をどうすればいいのですか?Linq:テイクの "反対"?

I.e.

aCollection.Take(n) 

最後のn個の要素以外はすべて取得したいと考えています。

aCollection.Leave(n) 

(なぜ:-)

編集

に聞かないでください、私は、私はそれをこのようaCollection.TakeWhile((x, index) => index < aCollection.Count - n)または拡張子

public static IEnumerable<TSource> Leave<TSource>(this IEnumerable<TSource> source, int n) 
{ 
    return source.TakeWhile((x, index) => index < source.Count() - n); 
} 

の形で行うことができたとのようなものしかし、の場合Linq to SQLまたはNHibernate Linqそれはニックだったでしょう(SQL Server/T-SQLの場合)

または他のより巧妙なSQLの実装。

私はそれのようなものは何もないと思いますか? (しかし編集が実際に問題の一部ではありませんでした。)

+0

注:これは、スキップと同じではありません! –

+0

うわー、あなたたちは速いです! Shedalのように見え、Jim Daggの答えは私の目的にとっては最高です。 これらのうちどれを正解として選択するかはどのようにして知ることができますか?ジムは速かったが、シェダーは票を得た。 –

+0

Shedalの答えを受け入れます。リバースはデータベース上では機能しません。データベースでは、ソートするフィールドの修飾子が本質的に必要です。ORMでテストするとランタイムエラーが発生します。私はShedalのコードをORMでテストしました。コードは正常に実行されています。 –

答えて

21
aCollection.Take(aCollection.Count() - n); 

EDIT:だけコメントで思い付いた興味深い情報の一部として - それはすべての要素を反復処理ですので、あなたは、IEnumerableの拡張メソッド.Count()が遅いと思うことがあります。しかし、実際のオブジェクトがICollectionまたはICollection<T>を実装する場合は、.Countというプロパティを使用するだけで、O(1)にする必要があります。その場合、パフォーマンスは損なわれません。

ソースコードはIEnumerable.Count()at TypeDescriptor.netです。

+0

'aCollection.Count()'を意味しますか? 'Length'は配列のプロパティです。 – Oded

+0

@Odedありがとうございました。最後に取る –

+0

も同様に必要ではありません。 –

11

私は、このための組み込みメソッドがありませんかなり確信しているが、これはReverseSkipをチェーン化することにより容易に行うことができます。

aCollection.Reverse().Skip(n).Reverse() 
+2

これは、 'aCollection.Skip(aCollection.Count() - n)'、 'n Oded

+1

Count()への1回の呼び出しのためにReverse()への2回の呼び出しを避けることは間違いありません。 – riwalk

+1

@Oded:私は同意し、私はすでにShedalの答えをupvotedしました。とにかく代わりの解決策として私のここに私を保つつもりです。 – Heinzi

5

私はそこに組み込み関数があるとは思わない。

aCollection.Take(aCollection.Count - n)

は適していなければなりません。コレクション内のアイテムの総数からnを引いた値は、最後のn個の要素をスキップする必要があります。

1

これは、リストが1つだけ作成され、リストを1回列挙するだけなので、ダブルリバースのソリューションよりはるかに効率的です。

public static class Extensions 
{ 
    static IEnumerable<T> Leave<T>(this IEnumerable<T> items, int numToSkip) 
    { 
     var list = items.ToList(); 
     // Assert numToSkip <= list count. 
     list.RemoveRange(list.Count - numToSkip, numToSkip); 
     return List 
    } 
} 


string alphabet = "abcdefghijklmnopqrstuvwxyz"; 
var chars = alphabet.Leave(10); // abcdefghijklmnop 
1

IEnumerable哲学を維持し、ICollectionが実装されていない、あなたはこれらの拡張メソッドを使用することができる場合のために、一度列挙介さ:

public static IEnumerable<T> Leave<T>(this ICollection<T> src, int drop) => src.Take(src.Count - drop); 

public static IEnumerable<T> Leave<T>(this IEnumerable<T> src, int drop) { 
    var esrc = src.GetEnumerator(); 
    var buf = new Queue<T>(); 
    while (drop-- > 0) 
     if (esrc.MoveNext()) 
      buf.Enqueue(esrc.Current); 
     else 
      break; 

    while (esrc.MoveNext()) { 
     buf.Enqueue(esrc.Current); 
     yield return buf.Dequeue(); 
    } 
}