Reputation: 467
I have a list of bool, and a list of strings. I want to use IEnumerable.Zip to combine the lists, so if the value at each index of the first list is true, the result contains the corresponding item from the second list.
In other words:
List<bool> listA = {true, false, true, false};
List<string> listB = {"alpha", "beta", "gamma", "delta"};
IEnumerable<string> result = listA.Zip(listB, [something]);
//result contains "alpha", "gamma"
The simplest solution I could come up with is:
listA.Zip(listB, (a, b) => a ? b : null).Where(a => a != null);
...but I suspect there's a simpler way to do this. Is there?
Upvotes: 5
Views: 1033
Reputation: 171178
I think this is simpler:
listA
.Zip(listB, (a, b) => new { a, b } )
.Where(pair => pair.a)
.Select(pair => pair.b);
That logically separates the steps. First, combine the lists. Next, filter. No funky conditionals, just read it top to bottom and immediately get it.
You can even name it properly:
listA
.Zip(listB, (shouldIncludeValue, value) => new { shouldIncludeValue, value } )
.Where(pair => pair.shouldIncludeValue)
.Select(pair => pair.value);
I love self-documenting, obvious code.
Upvotes: 10
Reputation: 21887
This is as short as I could get it:
var items = listB.Where((item, index) => listA[index]);
Where
has an overload that provides the index. You can use that to pull the corresponding item in the bool list.
Upvotes: 4
Reputation: 144126
You don't need to use Zip
if you can index into listA
:
var res = listB.Where((a, idx) => listA[idx]);
Upvotes: 0
Reputation: 125620
listA.Zip(listB, (a, b) => new { a, b }).Where(x => x.a).Select(x => x.b);
It uses anonymous type to handle Zip
method subresults.
Upvotes: 0