views:

133

answers:

2

I have a linq query that is querying over IEnumberable. When I have a matching element for my where clause I would like to know the position of the element in the IEnumberable.

var result = from e in elements
             where (string) e.Attribute("class") == "something"
             select e.Position();

The e.Position() of course does not compile. The value of e.Position() would be the position of the selected element in the elements IEnumberable.

Any ideas on how to do this?

+2  A: 

You need to use the overloaded Select method that allows for an index since that capability is not available in query syntax.

elements.Select((e, i) => new { Element = e, Index = i })
        .Where(item => (string)item.Element.Attribute("class") == "something")
        .Select(item => item.Index);
Ahmad Mageed
Thanks for quick reply.
Joel Cunningham
A: 

If you're using .NET 4.0 then you can use the (new) Zip method and write the same thing using the query syntax as well. It creates some temporary objects, so it isn't as efficient, but some people may find it more readable:

var result = from e in elements.Zip
               (Enumerable.Range(0, elements.Count()), Tuple.Create) 
             where (string)e.Item1.Attribute("class") == "something" 
             select e.Item2; 

It 'zips' the input collection with a generated sequence of numbers (with the same range as is the length of the collection). Then you can store the combined value either using the Tuple class (that's what I did) or you could use anonymous type.

Tomas Petricek