【问题标题】:Two Keys and A Value in A Dictionary字典中的两个键和一个值
【发布时间】:2018-03-10 05:51:16
【问题描述】:

我需要在字典中实现两个键,但有点卡住了。我不确定是否可以这样做,但我的标准是使用两个键在类似于以下 Linq 的字典数据结构中匹配一个搜索选项:

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

使用 Dictionary,我尝试了以下方法:

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>>
{

}

最后尝试将 Employee 类与数据绑定并使用 List:

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); 
}

它看起来已完成,但现在,我遇到了异常,其中一个是:'无法将 lambda 表达式转换为 System.Collections.Generic.IEComparer 类型,因为它不是委托类型' - ToDictionary(g => g.Key.CustomerId, g => g.Key.Status, g => g.ToList()。此行中的另一个错误:dict中的var item [id][status]。有没有办法摆脱它,并且可能在某处做错事。

【问题讨论】:

  • List>怎么样?
  • ToDictionary 返回Dictionary。你不能指望它会自动返回TwoKeyDictionary

标签: c# asp.net dictionary data-structures


【解决方案1】:

我会把你的字典改成这样:

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

因为您希望 int 和 string 都在一起并指定一个键。

另外,.ToDictionary 调用看起来像这样:

Dictionary<Tuple<int, string>, List<Employee>> dict = 
    employees.ToDictionary(g => 
        new Tuple<int, string>(g.Key.CustomerId, g.Key.Status), g => g);

【讨论】:

  • 我在这里再次遇到异常 - g => g.ToList() 它说 - 无法转换为 lambda 表达式以键入 > 因为它不是委托类型
  • 应该是g =&gt; g 而不是g =&gt; g.ToList(),因为“g”已经是List&lt;Employee&gt;
【解决方案2】:

为什么不使用tuple 作为键?

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

【讨论】:

    【解决方案3】:

    实际上,您已经可以做到这一点,而无需额外的类,甚至仅限于两个键。使用Lookup&lt;TKey, TElement&gt;,它使用匿名类型作为键:

    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);
    }
    

    查找类似于字典,但它允许有多个键并且始终存在一个值,即使对于非包含键也是如此。这怎么可能?如果不包含该键,则返回 Enumerable.Empty&lt;TValue&gt;,并返回同一键的一系列值。

    【讨论】:

    • 好的,感谢@Tim Schmelter 的想法。那么这是否意味着我尝试过的方式应该避免使用或有限制。没关系 - 我只是问,因为我不是这方面的专家。
    • @user8512043:嗯,你看到上面的代码和你的代码相比有多短,而且它可以工作。那么为什么要创建一个仅限于两个密钥对而不是无限的新字典类型呢?
    • 这是真的@Tim Schmelter。我只是想知道是否可以这样做。简单的事情真的更可取。再次感谢。
    猜你喜欢
    • 2015-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多