33

Suppose I have the array string[] weekDays = { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" }; , and I want to find out the index of array elements containing 's'. How can I do this using Linq ?

I've tried int[] indexOfDaysContainingS = weekDays.Where(day => day.Contains("s")).Select((day, index) => index).ToArray();, but this returns 0,1,2 as presumably it's getting the index of the filtered IEnumberable<string> after the Where() clause instead. If I put the Select() first, then all I have is the index and can't filter by the days.

What do I need to change to make it work and return 1,2,3 instead ?

1
  • I know that's not part of the question, but why don't use do this with a for loop instead of Linq. You would have saved many minutes of development. Commented Nov 20, 2010 at 11:17

3 Answers 3

44

You could do it this way:

weekDays.Select((day, index) => new { Day = day, Index = index })
        .Where(x => x.Day.Contains("s"))
        .Select(x => x.Index)
        .ToArray();

Not sure if this is optimal..

Sign up to request clarification or add additional context in comments.

2 Comments

@Patko but how did it know to take the index from the array and associate it with the "index" which you put in the Index property?
@YonatanNir, Select has two overloads, one also has an index of the element as a parameter, see msdn.microsoft.com/en-us/library/bb534869.aspx. That index parameter is then saved to an anonymous object so that it can be again used in the second Select. I hope this answers your question?
15

Patko's answer is the way to go in the general case.

Here are 2 more options:

// Idea only works with collections that can be accessed quickly by index.
int[] indices = Enumerable.Range(0, weekDays.Length)
                          .Where(index => weekDays[index].Contains("s"))
                          .ToArray();

With MoreLinq:

// Similar to Patko's idea, except using a 'named' type.
int[] indices = weekDays.AsSmartEnumerable()
                        .Where(item => item.Value.Contains("s"))
                        .Select(item => item.Index)
                        .ToArray();

2 Comments

Thanks for the alternatives. Is there any reason why performance would be different using your first alternative vs Patko's answer for a large array ? I'm not sure which is the optimal choice.
@miket2e: Patko's answer is the general one - the Range approach doesn't work well with non-list sequences; so it's hard to make a "fair" comparison. For arrays, I would think the Range approach would be faster - there's probably less heap allocation, it's possibly more cache-friendly etc. (notice the weasel words). Don't believe me though, measure! Maybe you shouldn't even be using LINQ here.
-3

This should work:

weekDays.Where(a => a.Contains("s")).Select((a, i) => i).ToArray();

1 Comment

I don't believe the logic is correct in this example as the index value returned shall be after the collection has already been filtered rather than the index relative to the original collection.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.