2

This is my sample data

var array = new string[]  { "q", "we", "r", "ty", " ", "r" };

I want to take items from this collection until one of them don't meet the criteria, for example:

x => string.IsNullOrEmpty(x);

So after this:

var array = new string[]  { "q", "we", "r", "ty", " ", "r" };
var newArray = array.TakeTo(x => string.IsNullOrEmpty(x));

newArray should contains: "q", "we", "r", "ty"

I created this code:

public static class Extensions
{
    public static int FindIndex<T>(this IEnumerable<T> items, Func<T, bool> predicate)
    {
        if (items == null) throw new ArgumentNullException("items");
        if (predicate == null) throw new ArgumentNullException("predicate");

        var retVal = 0;
        foreach (var item in items)
        {
            if (predicate(item)) return retVal;
            retVal++;
        }
        return -1;
    }

    public static IEnumerable<TSource> TakeTo<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
    {
        var index = source.FindIndex(predicate);

        if (index == -1)
            return source;

        return source.Take(index);
    }
}

var array = new string[]  { "q", "we", "r", "ty", " ", "r" };
var newArray = array.TakeTo(x => string.IsNullOrEmpty(x));

It works, but I am wondering if there is any built-in solution to that. Any ideas?

dafie
  • 951
  • 7
  • 25
  • 7
    What you want to use is [`TakeWhile`](https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.takewhile?view=net-6.0) with `x => !string.IsNullOrEmpty(x)` – juharr Jun 12 '22 at 12:24

1 Answers1

2

juharr mentioned in a comment that you should use TakeWhile, and it's likely exactly what you're looking for.

For your case, the code you'd be looking for is:

var array = new string[]  { "q", "we", "r", "ty", " ", "r" };
var newArray = array.TakeWhile(x => !string.IsNullOrWhiteSpace(x)).ToArray();

Notably, I've replaced IsNullOrEmpty with an IsNullOrWhiteSpace call, which is important as IsNullOrEmpty will return false if there's any whitespace present.

What TakeWhile does is essentially iterate through an enumerable's elements and subjects them to your given function, adding to a return collection until the function no longer returns true, at which point it stops iterating through the elements and returns what it's collected so far. In other words, it's "taking, while..." your given condition is met.

In your example, TakeWhile would stop collecting on your array variable's 4th index, since it contains only whitespace, and return "q", "we", "r", "ty".

Spevacus
  • 584
  • 2
  • 13
  • 23