Jimmy
Jimmy

Reputation: 3264

Lambda expression for getting indexes of list items conditionally

I have a List<bool>. I need to get the indexes of top n items where item value = true.

For example the following list items(bool)

10011001000

TopTrueIndexes(3) = The first 3 indexes where bits are true are 0, 3, 4 
TopTrueIndexes(4) = The first 4 indexes where bits are true are 0, 3, 4, 7 

How can I write a lambda for this?

Upvotes: 11

Views: 37959

Answers (4)

Jesse Gador
Jesse Gador

Reputation: 85

Here how it goes:

  1. Select source + its index
  2. Add condition to the where clause (the source of the where clause now contains the original source + index)
  3. Select the index (the index returned here is the original index from the original source)

var indexes = inputList.Select((input, index) => new { input, index }).Where(a => condition(a.input)).Select(a => a.index);

Upvotes: -1

kevingessner
kevingessner

Reputation: 18985

There's an overload of Select where the lambda gets two parameters: the index and the element. So you can just take the indices where the value is true, supplying a sentinel (here, -1) for the ones you don't want. Then filter out the sentinels and take how many you want:

bool[] bools = ...;
var indices = bools.Select((val, ix) => val ? ix : -1).Where(i => i >= 0).Take(n);

Upvotes: 2

Alxandr
Alxandr

Reputation: 12431

This should probably do it.

IEnumerable<bool> GetItemsInList(IEnumerable<bool> list, int count) {
    int ind = 0;
    return list.Select(itm => new {i = ind++, v = itm}).Where(itm => itm.v).Take(count).Select(itm => itm.i);
} 

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1502036

Well, assuming you have some easily-identifiable condition, you can do something like this, which will work for any IEnumerable<T>:

var query = source.Select((value, index) => new { value, index })
                  .Where(x => x.value => Condition(value))
                  .Select(x => x.index)
                  .Take(n);

(Obviously fill in the appropriate bit of the Where clause. If it's just a List<bool> it may just be x => x.value.)

The important bits are that you use the overload of Select to get index/value pairs before the Where, and then another Select to get just the indexes after the Where... and use Take to only get the first n results.

Upvotes: 42

Related Questions