0

I've a requirement to implement two keys in a dictionary and stuck a bit. I am not sure if it's possible to do but my criteria is to make a search option using two keys to match in a dictionary data structure similar to the below Linq:

if(id > 0 && status != null) { var result = (from c in db.Employees where c.EmployeeId == id && c.Status == status select c).ToList(); } 

With Dictionary, I've tried the following:

public class Employee { public int EmployeeId { get; set; } public string EmployeeName { get; set; } public string Address { get; set; } public string Status { get; set; } } public class TwoKeyDictionary<k1, k2, T> : Dictionary<k2, Dictionary<k2, T>> { } 

Finally tried to the bind the Employee class with data and used List<> for that:

List<Employee> employees = new List<Employee>() { new Employee { EmployeeId = 1001, EmployeeName = "John", Address = "On Earth", Status = "Active"}, new Employee { EmployeeId = 1002, EmployeeName = "Jack", Address = "On Earth", Status = "Active"}, new Employee { EmployeeId = 1003, EmployeeName = "James", Address = "On Earth", Status = "Inactive"}, new Employee { EmployeeId = 1004, EmployeeName = "Oswald", Address = "On Earth", Status = "Inactive"} }; int id = 0; string status = "" if (id > 0 && status != "") { id = Convert.ToInt32(Console.ReadLine()) status = Console.ReadLine().ToUpper(); } TwoKeyDictionary<int, string, List<Employee>> dict = employees.GroupBy(c => new { CustomerId = c.EmployeeId, c.Status }) .ToDictionary(g => g.Key.CustomerId, g => g.Key.Status, g => g.ToList()); foreach (var item in dict[id][status]) { Console.WriteLine(item.CustomerId + " " + item.CustomerName); } 

It looks completed but right now, I am having exceptions and the one is: 'Cannot convert to lambda expression to type System.Collections.Generic.IEComparer because it is not a delegate type' - ToDictionary(g => g.Key.CustomerId, g => g.Key.Status, g => g.ToList(). The other error in this line: var item in dict[id][status]. Is there any way to get rid of it and may be doing the wrong thing somewhere.

2
  • How about List<KeyValuePair<int, Employee>>? Commented Sep 28, 2017 at 13:11
  • ToDictionary return a Dictionary. You can't expect it to automagically return a TwoKeyDictionary. Commented Sep 28, 2017 at 13:14

3 Answers 3

3

I would change your dictionary to something like this:

Dictionary<Tuple<int, string>, List<Employee>> 

Because you want the int and the string to both be together and designate a key.

Also, the .ToDictionary call would look like this:

Dictionary<Tuple<int, string>, List<Employee>> dict = employees.ToDictionary(g => new Tuple<int, string>(g.Key.CustomerId, g.Key.Status), g => g); 
Sign up to request clarification or add additional context in comments.

2 Comments

I am having exception here again - g => g.ToList() and it says - Cannot convert to lambda expression to type <System.Tuple<int, string>> because it is not a delegate type
It should be g => g not g => g.ToList() because "g" is already a List<Employee>
1

Why not use a tuple as a key?

Dictionary<Tuple<K1, K2>, V> d1; 

Comments

0

Actually you can do that already without an additional class which is even limited to only two keys. Use a Lookup<TKey, TElement> which uses an anonymousy type as key:

var idStatusLookup = employees.ToLookup(x => new {x.EmployeeId, x.Status}); var matchingEmployees = idStatusLookup[new { EmployeeId = 1001, Status = "Active"}]; foreach (Employee emp in matchingEmployees) { Console.WriteLine(emp.EmployeeId + " " + emp.EmployeeName); } 

A lookup is similar to a dictionary but it allows to have multiple keys and there is always a value, even for non-contained keys. How is that possible? By returning Enumerable.Empty<TValue> if the key is not contained and by returning a sequence of values for the same key.

4 Comments

OK and thanks for the idea @Tim Schmelter. So does it mean in my way that I've tried should be avoided to use or have limitation. Never mind - I am just asking as I am not that expert in this.
@user8512043: well, you see how short the code above is compared to yours and it works. So why you want to create a new dictionary type that is limited to only two key-pairs instead of infinite?
That's true @Tim Schmelter. I was just wondering if it is possible to do. Simple things are really preferable. Thanks again.
@TimSchmelter the Lookup is not for 2 keys and 1 value, but for 1 key and an arbitrary number of values. If OP wanted the key "Bob" to have the values "fish" and "cheese", a Lookup is fine. However, they want the keys "fish" and "cheese", when used together, to have the value "Bob". learn.microsoft.com/en-us/dotnet/api/…

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.