2010-11-13 5 views
10

J'ai un List<bool>. J'ai besoin d'obtenir les index des n premiers éléments où la valeur de l'élément = true.Expression lambda pour obtenir les index des éléments de la liste conditionnellement

Par exemple, les éléments de liste suivants (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 

Comment puis-je écrire un lambda pour cela?

Répondre

30

Eh bien, en supposant que vous avez une condition facilement identifiable, vous pouvez faire quelque chose comme ça, qui travaillera pour touteIEnumerable<T>:

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

(remplissage Il est évident que dans le bit approprié du clause Where. Si c'est juste un List<bool> il peut juste être x => x.value.)

les bits importants sont que vous utilisez la surcharge de Select pour obtenir des paires index/valeur avant le Where, puis une autre Select pour obtenir juste les indices après la Where ... et utiliser Take pour obtenir que les premiers résultats n.

+4

Nice, je ne savais pas que vous pouviez faire Select ((val, ind) => ...). +1 – Alxandr

+0

@Alxandr: C'est l'une des choses que vous pouvez faire en appelant la méthode 'Select' directement, mais pas via une expression de requête. –

+0

@Jon. Excellent merci. – Jimmy

0

Cela devrait probablement le faire.

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); 
} 
+0

Cela donnera juste vrai, vrai, vrai, vrai ... 'count' fois. Ce n'est pas donner les * index *. –

+0

Désolé, vu cela aussi, et l'a réparé. – Alxandr

2

Il y a une surcharge de Select où le lambda obtient deux paramètres: l'index et l'élément. Donc, vous pouvez simplement prendre les indices où la valeur est vraie, en fournissant une sentinelle (ici, -1) pour ceux que vous ne voulez pas. Ensuite, filtrer les sentinelles et prendre combien vous voulez:

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

Vous avez l'index et l'élément dans l'ordre inverse dans votre lambda, ce qui va dérouter les gens (me confondre). Cela devrait être 'Select ((val, ix) ...'. – Mud