26

I have a dictionary of the type:

IDictionary<foo, IEnumerable<bar>> my_dictionary 

bar class looks like this:

class bar { public bool IsValid {get; set;} } 

How can I create another dictionary with only those items that have IsValid = true.

I tried this:

my_dictionary.ToDictionary( p=> p.Key, p=> p.Value.Where (x => x.IsValid)); 

The problem with above code is that this creates a key with empty enumerable, if all the elements for that key were IsValid = false.

for example:

my_dictionar[foo1] = new List<bar> { new bar {IsValid = false}, new bar {IsValid = false}, new bar {IsValid = false}}; my_dictionary[foo2] = new List<bar> {new bar {IsValid = true} , new bar{IsValid = false}; var new_dict = my_dictionary.ToDictionary( p=> p.Key, p=> p.Value.Where (x => x.IsValid)); // Expected new_dict should contain only foo2 with a list of 1 bar item. // actual is a new_dict with foo1 with 0 items, and foo2 with 1 item. 

How do I get my expected.

3 Answers 3

42

Something like this?

my_dictionary .Where(p=> p.Value.Any(x => x.IsValid)) .ToDictionary( p=> p.Key, p=> p.Value.Where (x => x.IsValid)); 

That will only include items where at least one of the values IsValid.

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

3 Comments

+1 OP needs to filter the collection using Where before calling ToDictionary
is this first Where clause not enough to get rid of x=>!x.IsValid ? Can You not just write .ToDictionary(p=>p.Key, p=>p.Value), since that where clause before calling ToDictionary is already applying filtering?
@Prokurors: No, because we're acting on an IEnumerable<KeyValuePair<foo, IEnumerable<bar>>>, it's a little more complicated than that. The first .Where() is checking whether any bar in each KeyValuePair is valid, but it's not actually filtering the bars themselves to only include valid ones. If you had a KeyValuePair whose value contained a mix of valid and invalid, the invalid ones would still need to be filtered out later.
1
my_dictionary.Where(p => p.Any(v => v.Value.IsValid()) .ToDictionary(p=> p.Key, p=> p.Value.Where(x => x.Value.IsValid()); 

Get Only the Items that have a true in the Value, then only get the items that are true into the new dictonary.

Filter then create the dictonary

Comments

1
var new_dict = my_dictionary.Select(x => new KeyValuePair<foo, List<bar>>( x.Key, x.Value .Where(y => y.IsValid) .ToList())) .Where(x => x.Value.Count > 0) .ToDictionary(x => x.Key, x => x.Value.AsReadOnly()); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.