Reputation: 4356
I have a dictionary where I have a List
as value. I want to select specific elements from the list that belongs to a specific key. I tried this so far:
Dictionary<int, List<bool>> dic = new Dictionary<int, List<bool>>();
dic.Add(1, new List<bool> { true, true, false });
var works = dic.Where(x => x.Key == 1).SingleOrDefault().Value.Where(x => x == true).ToList();
var doesNotWork = dic.Where(x => x.Key == 2).SingleOrDefault().Value.Where(x => x == true).ToList();
The first LINQ works because there is a key equal to 1. Thus I get a List<bool>
with two elements.
The second LINQ does not work because Value is null
. How can I rewrite that LINQ such that if there is no suitable key in the dictionary I get an empty List<bool>
?
I thought my approach would work because I thought the default element had an empty list instead of null as Value.
Upvotes: 2
Views: 19528
Reputation: 778
Disclaimer: This only works on C# 6.0 and later (VS 2015+)
If you really want to do it in a single line using linq you can use the ?.
operator (null-conditional operator) and get a line like this:
var shouldWork = dic.Where(x => x.Key == 2)?.SingleOrDefault().Value.Where(x => x == true).ToList() ?? new List<bool>();
This will set shouldWork to either the result of the linq query or an empty list. You can replace new List<bool>()
with anything you want
See MSDN post here and Github post here for information on the new features in C# 6.0 specifically this example from the github site:
int length = customers?.Length ?? 0; // 0 if customers is null
and description of how it works
The null-conditional operator exhibits short-circuiting behavior, where an immediately following chain of member accesses, element accesses and invocations will only be executed if the original receiver was not null
Edit: Since ?. checks for null, you could simplify the above linq query to this:
var shouldWork = dic[key]?.Where(x => x == true).ToList() ?? new List<bool>();
where key is some variable holding your key
Upvotes: 5
Reputation: 205569
You shouldn't be using LINQ to find a key in a Dictionary
- the Dictionary
has more efficient methods for doing that - ContainsKey
/ indexer pair or more optimal TryGetValue
.
For instance:
int key = 2;
(A)
var result = dic.ContainsKey(key) ? dic[key].Where(x => x == true).ToList() : new List<bool>();
(B)
List<bool> values;
var result = dic.TryGetValue(key, out values) ? values.Where(x => x == true).ToList() : new List<bool>();
Upvotes: 5
Reputation: 47
We don't know why it need to be LINQ, but this could be a option:
var nowItWork = dic.Where(x => x.Key == 2).SelectMany(x => x.Value).Where(x => x).ToList();
Upvotes: 0
Reputation: 31
Try this
Dictionary<int, List<bool>> dic = new Dictionary<int, List<bool>>();
dic.Add(1, new List<bool> { true, true, false });
var works = !dic.ContainsKey(1)? new List<bool>(): dic[1].Where(x => x == true).ToList();
var doesNotWork = !dic.ContainsKey(2) ? new List<bool>(): dic[2].Where(x => x == true).ToList();
Upvotes: 0
Reputation: 387
You want to get a strange result, but anyway this code help you:
var reslt = (dic.FirstOrDefault(x => x.Key == 2).Value ?? new List<bool>(0))
.Where(x => x)
.ToList();
Using method SingleOrDefault() isn't correct, because key in Dictionary is unique.
And x=>x==true is strange too.
Upvotes: 0
Reputation: 45096
Why does it need to be LINQ?
List<bool> works1 = dic.ContainsKey(1) ? dic[1] : new List<bool>();
Upvotes: 1
Reputation: 3082
Simplest solution would be to use Dictionary<T>.TryGetValue
so that you don't check twice for a value, ie:
Dictionary<int, List<bool>> dic = new Dictionary<int, List<bool>>();
dic.Add(1, new List<bool> { true, true, false });
List<bool> match = null;
var found = dic.TryGetValue(2, out match);
if (!found) match = new List<bool>();
Upvotes: 0