【问题标题】:Cannot add same key to dictionary more than once不能多次向字典添加相同的键
【发布时间】:2014-10-20 19:43:24
【问题描述】:

这是我的代码:

IEnumerable<ServiceTicket> troubletickets = db.ServiceTickets.Include(t => t.Company).Include(t => t.UserProfile);
var ticketGroups = new Dictionary<string, List<ServiceTicket>>();

ticketGroups = troubletickets
                .GroupBy(o => o.DueDate).ToDictionary(
                    group => {
                        var firstOrDefault = @group.FirstOrDefault();
                        return firstOrDefault != null
                            ? firstOrDefault.DueDate.HasValue
                                ? firstOrDefault.DueDate.Value.ToShortDateString()
                                : ""
                            : "";
                    },
                    group => group.ToList()
                ).OrderBy(g => g.Key).ToDictionary(g => g.Key, g => g.Value);

我得到的错误是:“已添加具有相同密钥的项目。”这是因为 DueDate 值偶尔会重复。我的问题是,如果字典中已经存在密钥,我该如何防止它被添加?

【问题讨论】:

  • 与其使用ToDictionary(),不如遍历查询中的项目并自己构建字典。你甚至可以创建自己的可枚举扩展ToDictionaryWithDuplicatedKeys()
  • 我已经编辑了你的标题。请参阅“Should questions include “tags” in their titles?”,其中的共识是“不,他们不应该”。
  • 您也可以使用HashSet - 添加重复键是可能的,但集合只包含该项目一次。但是像已经建议的那样应用 Distinct 可能会更容易。
  • 好吧,我正在尝试按日期对门票进行分组。例如。我想在 2014 年 10 月 20 日之前对所有票进行分组。所以,我想维护该组内的票。我试过 .GroupBy(o => o.DueDate).Distinct().ToDictionary()

标签: c# asp.net-mvc entity-framework dictionary


【解决方案1】:

您似乎是按一个值(DueDate 值)分组,但使用不同的值作为字典键。

您不能只使用自定义代码进行分组吗?

ticketGroups = troubletickets
                .GroupBy(o => o.DueDate.HasValue
                                ? o.DueDate.Value.ToShortDateString()
                                : "")
                .ToDictionary(g => g.Key, g => g.ToList());

请注意,我接听了我们多余的 OrderBy 和第二个 ToDictionary 电话 - 我假设您正在尝试“订购”该字典,因为没有订购普通字典。

【讨论】:

    【解决方案2】:

    您会得到重复的键,因为有两种方法可以将空字符串作为键,要么是空组,要么是空日期。副本将始终是空字符串。我想知道您是否真的打算在组为空时将空字符串作为键。反正没必要,以后可以随时过滤空组。

    先通过数据库引擎按日期(包括null)分组,然后在内存中应用字符串格式,这样更容易:

    IQueryable<ServiceTicket> troubletickets = db.ServiceTickets
                                                 .Include(t => t.Company)
                                                 .Include(t => t.UserProfile);
    
    Dictionary<string, List<ServiceTicket>> ticketGroups = 
                    troubletickets
                   .GroupBy(ticket => ticket.DueDate)
                   .AsEnumerable() // Continue in memory
                   .ToDictionary(g => g.Key.HasValue 
                                            ? g.Key.Value.ToShortDateString() 
                                            : string.Empty,
                                      g => g.Select(ticket => ticket));
    

    现在分组是按Key 值,而不是按组中的First 元素。 Key 永远不会为空,它始终是 Nullable&lt;DateTime&gt;,有或没有值。

    旁注:您会注意到 EF 不会生成 SQL group by 语句,这是因为 SQL 语句是“破坏性的”:它只返回分组列和聚合数据,而不是 LINQ @987654327 的单个记录@确实返回。因此,生成的 SQL 相当臃肿,如果将 AsEnumerable 放在 .GroupBy 之前,它可能会提高性能。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-10-29
      • 1970-01-01
      • 1970-01-01
      • 2017-11-24
      • 2021-08-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多