Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linq: Exclude results using Zip

Tags:

c#

linq

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?

like image 437
Ed Beaty Avatar asked Jan 10 '14 19:01

Ed Beaty


2 Answers

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.

like image 186
usr Avatar answered Oct 11 '22 22:10

usr


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.

like image 25
Dave Zych Avatar answered Oct 11 '22 20:10

Dave Zych