Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Don't take last record in linq C# [duplicate]

Tags:

c#

linq

We all know that Skip() can omit records that are not needed at the start of a collection.

But is there a way to Skip() records at the end of a collection?

How do you not take the last record in a collection?

Or do you have to do it via Take()

ie, the below code,

var collection = MyCollection

var listCount = collection.Count();

var takeList = collection.Take(listCount - 1);

Is this the only way exclude the last record in a collection?

like image 353
KyloRen Avatar asked Dec 18 '22 16:12

KyloRen


2 Answers

With enumerator you can efficiently delay yielding by one enumeration.

public static IEnumerable<T> WithoutLast<T>(this IEnumerable<T> source)
{
    using (IEnumerator<T> e = source.GetEnumerator()) 
    {
        if (e.MoveNext() == false) yield break;

        var current = e.Current;
        while (e.MoveNext())
        {
            yield return current;
            current = e.Current;
        }
    }   
}

Usage

var items = new int[] {};
items.WithoutLast(); // returns empty

var items = new int[] { 1 };
items.WithoutLast(); // returns empty

var items = new int[] { 1, 2 };
items.WithoutLast(); // returns { 1 }

var items = new int[] { 1, 2, 3 };
items.WithoutLast(); // returns { 1, 2 }
like image 183
Fabio Avatar answered Dec 24 '22 02:12

Fabio


A slightly different version of Henrik Hansen's answer:

static public IEnumerable<TSource> SkipLast<TSource>(
    this IEnumerable<TSource> source, int count)
{
    if (count < 0) count = 0;
    var queue = new Queue<TSource>(count + 1);
    foreach (TSource item in source)
    {
        queue.Enqueue(item);
        if (queue.Count > count) yield return queue.Dequeue();
    }
}
like image 22
Theodor Zoulias Avatar answered Dec 24 '22 02:12

Theodor Zoulias