Reputation: 45
I have dictionary with value being a list. I need to read each of the list's to extract a field. But getting the following error at the foreach loop
cannot convert type
System.Collections.Generic.List<UserQuery.Employee>
toUserQuery.Employee
It works if I use the firstorDefault as in the commented line for var iValue. But I will have multiple records to check in the dictionary that I am reading(though in this example, I hard coded 1, to test my code).
void Main()
{
var svalue =1;
List<Employee> emplist = new List<Employee>()
{
new Employee{ EID=10, Ename="John"},
new Employee{ EID=11, Ename="Adam"},
new Employee{ EID=12, Ename="Ram"}
};
List<Employee> emplist1 = new List<Employee>()
{
new Employee{ EID=1, Ename="Jo"},
new Employee{ EID=1, Ename="Ad"},
new Employee{ EID=1, Ename="Ra"}
};
var dict1 = new Dictionary<int, List<Employee>>();
dict1.Add(1, emplist);
dict1.Add(2, emplist1);
//var ivalue = dict1.FirstOrDefault(x => x.Key == svalue).Value.ToList();
var ivalue = dict1.Where(kvp => dict1.ContainsKey(1)).Select(x => x.Value);
Console.WriteLine(ivalue);
foreach (Employee emp in ivalue)
{
Console.WriteLine(emp.EID);
}
}
class Employee
{
public int EID { get; set;}
public string Ename {get; set;}
}
Upvotes: 1
Views: 306
Reputation: 186668
Your current code
var ivalue = dict1
.Where(kvp => dict1.ContainsKey(1)) //TODO: Very strange condition: check it
.Select(x => x.Value);
returns IEnumerable<List<Employee>>
as a result (ivalue
). Since you want IEnumerable<Employee>
only, you have to flatten the result:
var ivalue = dict1
.Where(kvp => dict1.ContainsKey(1))
.SelectMany(kvp => kvp.Value); // kvp: we still have key-value pair
However, it's not the way we deal with dictionaries; you're, probably, looking for something like this (let's preserve some Linq: - .Select(emp => emp.EID)
):
if (dict1.TryGetValue(1, out var ivalue)) // do we have corresponding value?
Console.WriteLine(String.Join(Environment.NewLine, ivalue // if yes, print them out
.Select(emp => emp.EID)));
Upvotes: 2
Reputation: 32058
That's not how you normally work with a Dictionary. What you want to do is something like this:
if (dict1.ContainsKey(1)) // if the dictionary contains the key
{
var ivalue = dict1[1]; // get the value of that key
}
With this, you are using the most effective way to search the dictionary. So you should do this instead:
var dict1 = new Dictionary<int, List<Employee>>();
dict1.Add(1, emplist);
dict1.Add(2, emplist1);
if (dict1.ContainsKey(1))
{
var ivalue = dict1[1];
Console.WriteLine(ivalue); // this will print System.Collections.Generic.List<Employee>
foreach (Employee emp in ivalue)
{
Console.WriteLine(emp.EID);
}
}
Another option is to use TryGetValue
:
var dict1 = new Dictionary<int, List<Employee>>();
dict1.Add(1, emplist);
dict1.Add(2, emplist1);
List<Employee> ivalue = null;
if (dict1.TryGetValue(1, out ivalue))
{
Console.WriteLine(ivalue); // this will print System.Collections.Generic.List<Employee>
foreach (Employee emp in ivalue)
{
Console.WriteLine(emp.EID);
}
}
Upvotes: 1
Reputation: 216243
The Where receives two times the KeyValuePair and of course returns true for both KeyValuePair because you ask always the same question. Does the dictionary contains the Key == 1? Yes. So the return from the Where is an enumerable of two List<Employee>
elements that cannot be converted to a single generic list.
var ivalue = dict1.FirstOrDefault(kvp => dict1.ContainsKey(1));
if(ivalue.Value != null)
foreach (Employee emp in ivalue.Value)
Console.WriteLine(emp.EID);
Of course, as pointed in comments, this use of Linq is unwarranted because your code could simplified with just
List<Employee> empList;
// Try directly to get the List<Employee> that match the Key
// if found you have the empList initialized with the matching list
// otherwise TryGetValue returns false.
if(dict.TryGetValue(1, out empList))
foreach (Employee emp in empList)
Console.WriteLine(emp.EID);
Upvotes: 0
Reputation: 148514
I don't think you've meant : dict1.ContainsKey(1))
I think you're after this :
var ivalue = dict1.FirstOrDefault(d =>d.Key==1 ).Value ;
if (ivalue!=null)
foreach (Employee emp in ivalue)
{
Console.WriteLine(emp.EID);
}
Notice that this :
var ivalue = dict1.Where(kvp => dict1.ContainsKey(1)).Select(x => x.Value);
checks if dictionary has 1 as key , but doesn't consider that key in results.
Upvotes: 0
Reputation: 3285
var ivalue = dict1.Where(kvp => dict1.ContainsKey(1)).Select(x => x.Value);
will return an 'IEnumerable' with elements of type List. so you would need two nested foreach loops:
the 'outer' one to iterate through all the lists retrieved from the Dictionary, the 'inner' one to iterate through all the employees in the current List.
Upvotes: 0
Reputation: 4733
When you do var ivalue = dict1.Where(kvp => dict1.ContainsKey(1)).Select(x => x.Value);
You're filtering your list with the Where
method and then selecting all the values with Select
.
It's normal that you get that exception, because Select gives you a list, not a single entry. You should either foreach
that list, or use FirstOrDefault
and get 1 single value.
foreach (var value in dict1.Where(kvp => dict1.ContainsKey(1)).Select(x => x.Value))
{
// ...
}
Or
var ivalue = dict1.Where(kvp => dict1.ContainsKey(1)).Select(x => x.Value).FirstOrDefault();
Upvotes: 0