Bir koleksiyonun son N öğesini almak için Linq mi kullanıyorsunuz?


284

Bir koleksiyon verildiğinde, bu koleksiyonun son N öğesini almanın bir yolu var mı? Çerçevede bir yöntem yoksa, bunu yapmak için bir uzantı yöntemi yazmanın en iyi yolu nedir?

Yanıtlar:


422
collection.Skip(Math.Max(0, collection.Count() - N));

Bu yaklaşım, herhangi bir sıralamaya bağımlı olmadan öğe sırasını korur ve çeşitli LINQ sağlayıcıları arasında geniş bir uyumluluğa sahiptir.

SkipNegatif bir numara ile arama yapmamaya dikkat etmek önemlidir . Varlık Çerçevesi gibi bazı sağlayıcılar, olumsuz bir argümanla sunulduğunda bir ArgumentException oluşturur. Bunu Math.Maxdüzgün bir şekilde önleme çağrısı .

Aşağıdaki sınıf, statik yöntem, statik yöntem ve thisanahtar kelimenin kullanımı gibi uzatma yöntemleri için gerekli tüm özelliklere sahiptir .

public static class MiscExtensions
{
    // Ex: collection.TakeLast(5);
    public static IEnumerable<T> TakeLast<T>(this IEnumerable<T> source, int N)
    {
        return source.Skip(Math.Max(0, source.Count() - N));
    }
}

Performans hakkında kısa bir not:

Çağrı çağrısı Count()belirli veri yapılarının numaralandırılmasına neden olabileceğinden, bu yaklaşım veri üzerinde iki geçişe neden olma riski taşır. Bu, enumerable'ların çoğunda bir sorun değil; aslında, Count()operasyonları O (1) zamanda değerlendirmek için Listeler, Diziler ve hatta EF sorguları için optimizasyonlar zaten mevcuttur .

Ancak, yalnızca ileriye doğru numaralandırılabilir bir numara kullanmanız gerekiyorsa ve iki geçiş yapmaktan kaçınmak istiyorsanız, Lasse V. Karlsen veya Mark Byers'ın tanımladığı gibi tek geçişli bir algoritmayı düşünün . Bu yaklaşımların her ikisi de, numaralandırma sırasında öğeleri tutmak için geçici bir tampon kullanırlar; bu, koleksiyonun sonu bulunduğunda verilir.


2
+1, bu Linq to Entities / SQL'de çalıştığı için. Sanırım Linq'dan Nesnelere James Curran'ın stratejisinden daha fazla performans sergiliyor.
StriplingWarrior

11
Koleksiyonun niteliğine bağlıdır. Count () O (N) olabilir.
James Curran

3
@James: Kesinlikle doğru. IEnumerable koleksiyonlarıyla kesinlikle ilgileniyorsanız, bu iki geçişli bir sorgu olabilir. 1 geçişli garantili algoritma görmekle çok ilgilenirim. Yararlı olabilir.
kbrimington

4
Bazı kriterler yaptım. Nesnelerin LINQ'su, kullandığınız koleksiyonun türüne göre bazı optimizasyonlar gerçekleştirir. Diziler, Lists ve LinkedLists kullanarak , James'in çözümü büyüklük sırasına göre olmasa da daha hızlı olma eğilimindedir. IEnumerable hesaplanırsa (Enumerable.Range aracılığıyla), James'in çözümü daha uzun sürer. Uygulama hakkında bir şey bilmeden veya değerleri farklı bir veri yapısına kopyalamaksızın tek bir geçiş garanti etmenin hiçbir yolunu düşünemiyorum.
StriplingWarrior

1
@RedFilter - Yeterince adil. Sanırım sayfalama alışkanlıklarım burada sızdı. Keskin gözünüz için teşekkürler.
kbrimington

59
coll.Reverse().Take(N).Reverse().ToList();


public static IEnumerable<T> TakeLast<T>(this IEnumerable<T> coll, int N)
{
    return coll.Reverse().Take(N).Reverse();
}

GÜNCELLEME: clintp sorununu çözmek için: a) Yukarıda tanımladığım TakeLast () yöntemini kullanmak sorunu çözer, ancak ekstra yöntem olmadan gerçekten yapmak istiyorsanız, Enumerable.Reverse () bir uzantı yöntemi olarak kullanıldığında, bunu şu şekilde kullanmanız gerekmez:

List<string> mystring = new List<string>() { "one", "two", "three" }; 
mystring = Enumerable.Reverse(mystring).Take(2).Reverse().ToList();

Ben bununla, ben diyorum ki sorun: List<string> mystring = new List<string>() { "one", "two", "three" }; mystring = mystring.Reverse().Take(2).Reverse(); .Reverse () void döndürür ve derleyici bir IEnumerable döndüren Linq yerine bu yöntemi seçer çünkü derleyici hatası alıyorum. Öneriler?
Clinton Pierce

1
Bu sorunu açık bir şekilde mystring'i IEnumerable <String>: ((IEnumerable <String>) mystring) 'e çevirerek çözebilirsiniz .Reverse (). (2) .Reverse ()
Jan Hettich

Kolay ve basit ama sipariş iki kez tamamen geri gerektirir. Bu en iyi yol olabilir
shashwat

Kbrimington'dan kabul edilen cevaba ek olarak hoşuma gitti. Son Nkayıtlardan sonra siparişi önemsemiyorsanız, ikinciyi atlayabilirsiniz Reverse.
ZoolWay

@shashwat Sırayı iki kez "tamamen" tersine çevirmez. İkinci geri dönüş yalnızca N öğelerin toplanması için geçerlidir. Ayrıca, Reverse () yönteminin nasıl uygulandığına bağlı olarak, yalnızca N öğeyi tersine çevirebilir. (.NET 4.0 uygulaması koleksiyonu bir diziye kopyalar ve geriye doğru dizine ekler)
James Curran

47

Not : Linq Kullanımı adlı soru başlığınızı kaçırdım , bu yüzden cevabım aslında Linq kullanmıyor.

Tüm koleksiyonun tembel olmayan bir kopyasını önbelleğe almaktan kaçınmak istiyorsanız, bağlantılı bir liste kullanarak bunu yapan basit bir yöntem yazabilirsiniz.

Aşağıdaki yöntem, orijinal koleksiyonda bulduğu her bir değeri bağlantılı bir listeye ekler ve bağlantılı listeyi gereken öğe sayısına kısaltır. Koleksiyon boyunca yineleme yoluyla bağlantılı listeyi bu sayıda öğeye kesilmiş halde tuttuğundan, orijinal koleksiyondan yalnızca en fazla N öğenin bir kopyasını tutar.

Orijinal koleksiyondaki öğelerin sayısını bilmenizi veya birden fazla kez yinelemenizi gerektirmez.

Kullanımı:

IEnumerable<int> sequence = Enumerable.Range(1, 10000);
IEnumerable<int> last10 = sequence.TakeLast(10);
...

Genişletme yöntemi:

public static class Extensions
{
    public static IEnumerable<T> TakeLast<T>(this IEnumerable<T> collection,
        int n)
    {
        if (collection == null)
            throw new ArgumentNullException(nameof(collection));
        if (n < 0)
            throw new ArgumentOutOfRangeException(nameof(n), $"{nameof(n)} must be 0 or greater");

        LinkedList<T> temp = new LinkedList<T>();

        foreach (var value in collection)
        {
            temp.AddLast(value);
            if (temp.Count > n)
                temp.RemoveFirst();
        }

        return temp;
    }
}

Teknik olarak Linq kullanmasa bile iyi, geçerli bir cevabınız olduğunu düşünüyorum, bu yüzden size hala bir +1 veriyorum :)
Matthew Groves

temiz, temiz ve genişletilebilir +1!
Yasser Shaikh

1
Kaynak numaralandırıcının iki kez (veya daha fazla) geçmesine neden olmayan ve numaralandırmanın gerçekleştirilmesini zorlamayan tek çözüm olduğunu düşünüyorum, bu yüzden çoğu uygulamada bunun açısından çok daha verimli olacağını söyleyebilirim bellek ve hız.
Sprotty

30

Aşağıda numaralandırılabilen ancak yalnızca O (N) geçici depolama alanı kullanan bir yöntem verilmiştir:

public static class TakeLastExtension
{
    public static IEnumerable<T> TakeLast<T>(this IEnumerable<T> source, int takeCount)
    {
        if (source == null) { throw new ArgumentNullException("source"); }
        if (takeCount < 0) { throw new ArgumentOutOfRangeException("takeCount", "must not be negative"); }
        if (takeCount == 0) { yield break; }

        T[] result = new T[takeCount];
        int i = 0;

        int sourceCount = 0;
        foreach (T element in source)
        {
            result[i] = element;
            i = (i + 1) % takeCount;
            sourceCount++;
        }

        if (sourceCount < takeCount)
        {
            takeCount = sourceCount;
            i = 0;
        }

        for (int j = 0; j < takeCount; ++j)
        {
            yield return result[(i + j) % takeCount];
        }
    }
}

Kullanımı:

List<int> l = new List<int> {4, 6, 3, 6, 2, 5, 7};
List<int> lastElements = l.TakeLast(3).ToList();

Elemanları gördükleri gibi saklamak ve eski elemanların üzerine yenilerini yazmak için N boyutunda bir halka tamponu kullanarak çalışır. Numaralandırılabilenin sonuna ulaşıldığında halka tamponu son N elemanlarını içerir.


2
+1: Bu benimkinden daha iyi bir performansa sahip olmalı, ancak koleksiyon daha az öğe içerdiğinde doğru olanı yaptığından emin olmalısınız n.
Lasse V. Karlsen

Çoğu zaman, insanların üretim amacıyla bu tür şeyleri kendileri eklemek için kod kopyalarken dikkat edeceklerini varsayıyorum, bu bir sorun olmayabilir. Ekleyecekseniz, koleksiyon değişkenini de null için kontrol etmeyi düşünün. Aksi takdirde, mükemmel bir çözüm :) Bağlantılı bir liste GC basıncı ekleyeceğinden, kendim bir halka tamponu kullanmayı düşünüyordum, ancak bir süredir yaptım ve test koduyla uğraşmak istemedim. eğer doğru yapsaydım. Ama LINQPad'a
Lasse V. Karlsen

2
Olası bir optimizasyon, sayılabilir IList'in uygulanıp uygulanmadığını kontrol etmek ve eğer varsa önemsiz çözümü kullanmak olacaktır. Geçici depolama yaklaşımı daha sonra yalnızca gerçekten 'akış' IEnumerables için gerekli olacaktır
piers7

1
önemsiz nit-pick: ArgumentOutOfRangeException için argümanlarınız yanlış sırada (R # diyor)
piers7

28

.NET Core 2.0+, LINQ yöntemini sağlar TakeLast():

https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.takelast

örnek :

Enumerable
    .Range(1, 10)
    .TakeLast(3) // <--- takes last 3 items
    .ToList()
    .ForEach(i => System.Console.WriteLine(i))

// outputs:
// 8
// 9
// 10

Şunu kullanıyorum: NET Standard 2.0 ve mevcut değil. Sorun nedir? :(
SuperJMN

@SuperJMN .net standart 2.0 kitaplıklarına başvuruyor olsanız da, projenizde doğru dotnet core sürümünü hedeflemiyor olabilirsiniz. Bu yöntem v1.x ( netcoreapp1.x) için değil, yalnızca dotnetcore ( netcoreapp2.x) ' ın v2.0 ve v2.1 sürümü için kullanılabilir . Belki net472de desteklenmeyen tam çerçeveyi (ör. ) Hedeflemeniz mümkündür . (.net standart kütüphaneleri yukarıdakilerden herhangi biri tarafından kullanılabilir, ancak yalnızca hedef çerçeveye özgü bazı API'ları gösterebilir. bkz. docs.microsoft.com/en-us/dotnet/standard/frameworks )
Ray

1
Bunların şimdi daha yüksek olması gerekiyor. Tekerleği yeniden icat etmeye gerek yok
James Woodley

11

Kimsenin bahsetmediğine şaşırdım, ancak SkipWhile öğenin dizinini kullanan bir yöntem var .

public static IEnumerable<T> TakeLastN<T>(this IEnumerable<T> source, int n)
{
    if (source == null)
        throw new ArgumentNullException("Source cannot be null");

    int goldenIndex = source.Count() - n;
    return source.SkipWhile((val, index) => index < goldenIndex);
}

//Or if you like them one-liners (in the spirit of the current accepted answer);
//However, this is most likely impractical due to the repeated calculations
collection.SkipWhile((val, index) => index < collection.Count() - N)

Bu çözümün diğerlerine göre sunduğu tek algılanabilir fayda, IEnumerable'ı iki kez çaprazlayan iki ayrı işleme sahip olmak yerine, daha güçlü ve etkili bir LINQ sorgusu yapmak için bir yüklem ekleme seçeneğine sahip olabilmenizdir.

public static IEnumerable<T> FilterLastN<T>(this IEnumerable<T> source, int n, Predicate<T> pred)
{
    int goldenIndex = source.Count() - n;
    return source.SkipWhile((val, index) => index < goldenIndex && pred(val));
}

9

RX Sisteminde EnumerableEx.TakeLast kullanın.Interactive assembly. @ Mark'ınki gibi bir O (N) uygulamasıdır, ancak bir halka tampon yapısı yerine bir kuyruk kullanır (ve tampon kapasitesine ulaştığında öğeleri ayıklar).

(Not: Bu IEnumerable sürümü - IObservable sürümü değil, ikisinin uygulanması hemen hemen aynı)


Bu en iyi cevap. İşi yapan ve RX ekibi yüksek kalitede uygun bir kütüphane varsa kendinizinkini yuvarlamayın.
bradgonesurfing

Bununla devam ediyorsanız, Nuget - nuget.org/packages/Ix-Async
nikib3ro

C # Queue<T>, dairesel bir arabellek kullanılarak uygulanmıyor mu?
tigrou

@tigrou. hayır, dairesel değil
citykid


6

Anahtarlı bir koleksiyonla uğraşıyorsanız (örn. Bir veritabanından girişler) hızlı (yani seçilen cevaptan daha hızlı) bir çözüm

collection.OrderByDescending(c => c.Key).Take(3).OrderBy(c => c.Key);

+1 benim için çalışıyor ve okuması kolay, listemde az sayıda nesne var
fubo

5

Monad'ın bir parçası olarak Rx'e dalmak sakıncası yoksa, şunları kullanabilirsiniz TakeLast:

IEnumerable<int> source = Enumerable.Range(1, 10000);

IEnumerable<int> lastThree = source.AsObservable().TakeLast(3).AsEnumerable();

2
Eğer (Cevabımı bakınız) yerine System.Reactive ait RX en System.Interactive başvuru varsa AsObservable () gerek yoktur
piers7


2

Verimliliği ve sadeliği birleştirmeye çalıştım ve bununla sonuçlandım:

public static IEnumerable<T> TakeLast<T>(this IEnumerable<T> source, int count)
{
    if (source == null) { throw new ArgumentNullException("source"); }

    Queue<T> lastElements = new Queue<T>();
    foreach (T element in source)
    {
        lastElements.Enqueue(element);
        if (lastElements.Count > count)
        {
            lastElements.Dequeue();
        }
    }

    return lastElements;
}

Performans hakkında: C # 'da, dairesel bir arabellekQueue<T> kullanılarak uygulanır , böylece her döngüde nesne nesnesi yapılmaz (yalnızca kuyruk büyürken). Birisi bu uzantıyı çağırabilir çünkü kuyruk kapasitesi (özel oluşturucu kullanarak) ayarlamadı . Ekstra performans için, kaynak uygulamasının olup olmadığını kontrol edebilir ve evet ise, dizi dizinlerini kullanarak doğrudan son değerleri ayıklayabilirsiniz.count = int.MaxValueIList<T>


1

Yukarıdaki tüm çözümler koleksiyon boyunca yineleme gerektirdiğinden, LINQ kullanarak bir koleksiyonun son N'sini almak biraz verimsizdir. TakeLast(int n)içinde System.Interactivede bu problem var.

Bir listeniz varsa, daha etkili bir şey aşağıdaki yöntemi kullanarak dilimlemektir

/// Select from start to end exclusive of end using the same semantics
/// as python slice.
/// <param name="list"> the list to slice</param>
/// <param name="start">The starting index</param>
/// <param name="end">The ending index. The result does not include this index</param>
public static List<T> Slice<T>
(this IReadOnlyList<T> list, int start, int? end = null)
{
    if (end == null)
    {
        end = list.Count();
    }
     if (start < 0)
    {
        start = list.Count + start;
    }
     if (start >= 0 && end.Value > 0 && end.Value > start)
    {
        return list.GetRange(start, end.Value - start);
    }
     if (end < 0)
    {
        return list.GetRange(start, (list.Count() + end.Value) - start);
    }
     if (end == start)
    {
        return new List<T>();
    }
     throw new IndexOutOfRangeException(
        "count = " + list.Count() + 
        " start = " + start +
        " end = " + end);
}

ile

public static List<T> GetRange<T>( this IReadOnlyList<T> list, int index, int count )
{
    List<T> r = new List<T>(count);
    for ( int i = 0; i < count; i++ )
    {
        int j=i + index;
        if ( j >= list.Count )
        {
            break;
        }
        r.Add(list[j]);
    }
    return r;
}

ve bazı test senaryoları

[Fact]
public void GetRange()
{
    IReadOnlyList<int> l = new List<int>() { 0, 10, 20, 30, 40, 50, 60 };
     l
        .GetRange(2, 3)
        .ShouldAllBeEquivalentTo(new[] { 20, 30, 40 });
     l
        .GetRange(5, 10)
        .ShouldAllBeEquivalentTo(new[] { 50, 60 });

}
 [Fact]
void SliceMethodShouldWork()
{
    var list = new List<int>() { 1, 3, 5, 7, 9, 11 };
    list.Slice(1, 4).ShouldBeEquivalentTo(new[] { 3, 5, 7 });
    list.Slice(1, -2).ShouldBeEquivalentTo(new[] { 3, 5, 7 });
    list.Slice(1, null).ShouldBeEquivalentTo(new[] { 3, 5, 7, 9, 11 });
    list.Slice(-2)
        .Should()
        .BeEquivalentTo(new[] {9, 11});
     list.Slice(-2,-1 )
        .Should()
        .BeEquivalentTo(new[] {9});
}

1

Bu soruya cevap vermek için geç olduğunu biliyorum. Ancak, IList <> türünde bir koleksiyonla çalışıyorsanız ve döndürülen koleksiyonun sırasını umursamıyorsanız, bu yöntem daha hızlı çalışır. Mark Byers cevapını kullandım ve küçük değişiklikler yaptım. Şimdi TakeLast yöntemi:

public static IEnumerable<T> TakeLast<T>(IList<T> source, int takeCount)
{
    if (source == null) { throw new ArgumentNullException("source"); }
    if (takeCount < 0) { throw new ArgumentOutOfRangeException("takeCount", "must not be negative"); }
    if (takeCount == 0) { yield break; }

    if (source.Count > takeCount)
    {
        for (int z = source.Count - 1; takeCount > 0; z--)
        {
            takeCount--;
            yield return source[z];
        }
    }
    else
    {
        for(int i = 0; i < source.Count; i++)
        {
            yield return source[i];
        }
    }
}

Test için Mark Byers yöntemini ve kbrimington andswer kullandım . Bu test:

IList<int> test = new List<int>();
for(int i = 0; i<1000000; i++)
{
    test.Add(i);
}

Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();

IList<int> result = TakeLast(test, 10).ToList();

stopwatch.Stop();

Stopwatch stopwatch1 = new Stopwatch();
stopwatch1.Start();

IList<int> result1 = TakeLast2(test, 10).ToList();

stopwatch1.Stop();

Stopwatch stopwatch2 = new Stopwatch();
stopwatch2.Start();

IList<int> result2 = test.Skip(Math.Max(0, test.Count - 10)).Take(10).ToList();

stopwatch2.Stop();

İşte 10 element almak için sonuçlar:

resim açıklamasını buraya girin

1000001 element almak için sonuçlar: resim açıklamasını buraya girin


1

İşte benim çözümüm:

public static class EnumerationExtensions
{
    public static IEnumerable<T> TakeLast<T>(this IEnumerable<T> input, int count)
    {
        if (count <= 0)
            yield break;

        var inputList = input as IList<T>;

        if (inputList != null)
        {
            int last = inputList.Count;
            int first = last - count;

            if (first < 0)
                first = 0;

            for (int i = first; i < last; i++)
                yield return inputList[i];
        }
        else
        {
            // Use a ring buffer. We have to enumerate the input, and we don't know in advance how many elements it will contain.
            T[] buffer = new T[count];

            int index = 0;

            count = 0;

            foreach (T item in input)
            {
                buffer[index] = item;

                index = (index + 1) % buffer.Length;
                count++;
            }

            // The index variable now points at the next buffer entry that would be filled. If the buffer isn't completely
            // full, then there are 'count' elements preceding index. If the buffer *is* full, then index is pointing at
            // the oldest entry, which is the first one to return.
            //
            // If the buffer isn't full, which means that the enumeration has fewer than 'count' elements, we'll fix up
            // 'index' to point at the first entry to return. That's easy to do; if the buffer isn't full, then the oldest
            // entry is the first one. :-)
            //
            // We'll also set 'count' to the number of elements to be returned. It only needs adjustment if we've wrapped
            // past the end of the buffer and have enumerated more than the original count value.

            if (count < buffer.Length)
                index = 0;
            else
                count = buffer.Length;

            // Return the values in the correct order.
            while (count > 0)
            {
                yield return buffer[index];

                index = (index + 1) % buffer.Length;
                count--;
            }
        }
    }

    public static IEnumerable<T> SkipLast<T>(this IEnumerable<T> input, int count)
    {
        if (count <= 0)
            return input;
        else
            return input.SkipLastIter(count);
    }

    private static IEnumerable<T> SkipLastIter<T>(this IEnumerable<T> input, int count)
    {
        var inputList = input as IList<T>;

        if (inputList != null)
        {
            int first = 0;
            int last = inputList.Count - count;

            if (last < 0)
                last = 0;

            for (int i = first; i < last; i++)
                yield return inputList[i];
        }
        else
        {
            // Aim to leave 'count' items in the queue. If the input has fewer than 'count'
            // items, then the queue won't ever fill and we return nothing.

            Queue<T> elements = new Queue<T>();

            foreach (T item in input)
            {
                elements.Enqueue(item);

                if (elements.Count > count)
                    yield return elements.Dequeue();
            }
        }
    }
}

Kod biraz tıknaz, ancak bir yeniden kullanılabilir bileşen olarak, çoğu senaryoda olduğu kadar iyi performans göstermeli ve onu kullanan kodu güzel ve özlü tutacaktır. :-)

Benim TakeLastiçin olmayanIList`1 , @Mark Byers ve @MackieChan'ın yanıtlarında olduğu gibi aynı halka tampon algoritmasına dayanmaktadır. Ne kadar benzer oldukları ilginç - benimkini tamamen bağımsız yazdım. Sanırım düzgün bir halka tamponu yapmanın sadece bir yolu var. :-)

@ Kbrimington'ın cevabına baktığımızda, IQuerable<T>Entity Framework ile iyi çalışan yaklaşıma geri dönmek için ek bir kontrol eklenebilir - bu noktada sahip olduğum şeyin olmadığını varsayalım .


0

Bir koleksiyondan (dizi) son 3 öğenin nasıl alınacağının gerçek örneğinin altında:

// split address by spaces into array
string[] adrParts = adr.Split(new string[] { " " },StringSplitOptions.RemoveEmptyEntries);
// take only 3 last items in array
adrParts = adrParts.SkipWhile((value, index) => { return adrParts.Length - index > 3; }).ToArray();

0

Tüm Aralığı Hatasız Almak İçin Bu Yöntemi Kullanma

 public List<T> GetTsRate( List<T> AllT,int Index,int Count)
        {
            List<T> Ts = null;
            try
            {
                Ts = AllT.ToList().GetRange(Index, Count);
            }
            catch (Exception ex)
            {
                Ts = AllT.Skip(Index).ToList();
            }
            return Ts ;
        }

0

Dairesel tampon kullanımı ile biraz farklı uygulama. Kriterler yöntem dolaylarında iki kat daha hızlı kullanarak olanlardan daha olduğunu göstermektedir Kuyruk (uygulanması TakeLast içinde System.Linq bu size olsa bile, elemanların istenilen sayı ile birlikte büyüyen bir tampon ihtiyacı - ancak bir maliyet olmadan,) küçük koleksiyon büyük bellek ayırma alabilirsiniz.

public IEnumerable<T> TakeLast<T>(IEnumerable<T> source, int count)
{
    int i = 0;

    if (count < 1)
        yield break;

    if (source is IList<T> listSource)
    {
        if (listSource.Count < 1)
            yield break;

        for (i = listSource.Count < count ? 0 : listSource.Count - count; i < listSource.Count; i++)
            yield return listSource[i];

    }
    else
    {
        bool move = true;
        bool filled = false;
        T[] result = new T[count];

        using (var enumerator = source.GetEnumerator())
            while (move)
            {
                for (i = 0; (move = enumerator.MoveNext()) && i < count; i++)
                    result[i] = enumerator.Current;

                filled |= move;
            }

        if (filled)
            for (int j = i; j < count; j++)
                yield return result[j];

        for (int j = 0; j < i; j++)
            yield return result[j];

    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.