15

Linqを使用する; どうすればTakeの「反対」を行うことができますか?

つまり、次のように最初のn個の要素を取得する代わりに

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 toSQLまたはNHibernateLinqの場合、生成されたSQLがそれを処理し、(SQL Server / T-SQLの場合)のようなものを生成したとしたら良かったでしょう。

SELECT TOP(SELECT COUNT(*) -@n FROM ATable) * FROM ATableまたは、他のより巧妙なSQL実装。

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

4

6 に答える 6

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

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

IEnumerable.Count() TypeDescriptor.netでのソースコードを見ることができます。

于 2012-04-20T14:05:19.667 に答える
11

このための組み込みのメソッドはないと確信していますが、これはチェーンReverseSkip:によって簡単に実行できます。

aCollection.Reverse().Skip(n).Reverse()
于 2012-04-20T14:04:57.043 に答える
5

このための組み込み関数があるとは思いません。

aCollection.Take(aCollection.Count - n)

適切である必要があります。コレクション内のアイテムの総数からnを引いたものを取得すると、最後のn個の要素をスキップする必要があります。

于 2012-04-20T14:06:48.647 に答える
3

哲学を維持し、実装されていないIEnumerable場合に1回列挙を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) {
    IEnumerable<T> IEnumHelper() {
        using (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();
            }
        }
    }

    return (src is ICollection<T> csrc) ? csrc.Leave(drop) : IEnumHelper();
}
于 2018-01-11T19:39:04.417 に答える
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
于 2012-04-20T14:15:54.490 に答える
-2

現在、C#にはTakeLast(n)、文字列の末尾から文字を取得するメソッドが定義されています。

ここを参照してください:https ://msdn.microsoft.com/en-us/library/hh212114(v = vs.103).aspx

于 2018-05-20T16:30:32.280 に答える