San
San

Reputation: 2346

Determine the position of an element in an IQueryable

I have a IQueryable which is ordered by some condition. Now I want to know the position of a particular element in that IQueryable. Is there a linq expression to get that. Say for example there are 10 elements in the IQueryable and the 6th element matches a condition, I want to get the number 6.

Upvotes: 11

Views: 10093

Answers (3)

Jason
Jason

Reputation: 3806

You can also use the verson of the "Where" function that incldes the collection index as a parameter to the predicate function. See MSDN for more info.

var result = Enumerable.Range(0, 10).Where((x, i) => i == 6);

The version could result in an empty list if there isn't a 6th element. Also this doesn't evaluate the where clause until you iterate over the result.

Upvotes: 0

Mark Byers
Mark Byers

Reputation: 838796

First select each item with its index, then filter the items, and finally extract the original index:

var result = orderedList
    .Select((x, i) => new { Item = x, Index = i })
    .Where(itemWithIndex => itemWithIndex.Item.StartsWith("g"))
    .FirstOrDefault();

int index= -1;
if (result != null)
    index = result.Index;

Test bed:

class Program
{
    static void Main(string[] args)
    {
        var orderedList = new List<string>
        {
            "foo", "bar", "baz", "qux", "quux",
            "corge", "grault", "garply", "waldo",
            "fred", "plugh", "xyzzy", "thud"
        }.OrderBy(x => x);

        // bar, baz, corge, foo, fred, garply, grault,
        // plugh, quux, qux, thud, waldo, xyzzy
        // Find the index of the first element beginning with 'g'.

        var result = orderedList
            .Select((x, i) => new { Item = x, Index = i })
            .Where(itemWithIndex => itemWithIndex.Item.StartsWith("g"))
            .FirstOrDefault();

        int index= -1;
        if (result != null)
            index = result.Index;

        Console.WriteLine("Index: " + index);
    }
}

Output:

Index: 5

Upvotes: 16

C. A. McCann
C. A. McCann

Reputation: 77404

You could use something like query.TakeWhile(x => !matchesCondition(x)).Count(), though that has the effect of enumerating the preceding values, which may not be what you want.

Upvotes: 2

Related Questions