【问题标题】:Implementing Dictionary with multiple Search Keys and Value使用多个搜索键和值实现字典
【发布时间】:2019-12-20 21:55:08
【问题描述】:

我在计划表中有一个包含 40,000 行的列表,其值基于五个关键列。表是这样的——

Date    Location    Schedule Id Type    Lane    Value
1/1/2019    Paris   Sched - 1   Rural   <null>  34.94
1/1/2019    Paris   Sched - 1   Rural   <null>  35.41
1/1/2019    Paris   Sched - 1   Rural    101    39.45
1/1/2019    Paris   Sched - 1   Urban    101    94.23
1/1/2019    Paris   Sched - 1   <null>   101    24.87
1/1/2019    Paris   Sched - 1   <null>  <null>  33.38

我需要处理数百万条记录,以根据每条记录中的键查找值。一条记录可能包含键的任意组合,其中前三个键是强制性的,但接下来的两个键可能有也可能没有值。对于这五个键的组合,Schedule 表具有唯一的行

我正在寻找有关用于存储计划表的正确数据结构的建议。我想过使用列表,但据我了解,列表不如字典高效,但字典只能用一个键定义。

如果有人可以提出更好的方法来实施此解决方案,请不胜感激。

--- Edit --

一个小的修正。通过“但接下来的两个键可能有也可能没有值”。我的意思是,它们可能有空值,但前 5 个键的组合仍然是唯一的。

【问题讨论】:

  • 字典只能有一个键,但这并不意味着键本身不能是包含您需要的许多不同属性的类型...
  • 使用字典, decimal>
  • 为什么不将此委托给具有适当索引的 SQL 数据库?
  • "processing million of records" -- 使用 SQL
  • 您声明 Schedule 表具有这五个键组合的唯一行,但示例数据集中的前两行具有相同的键。那么,您的数据中是否存在重复项?

标签: c# dictionary data-structures lookup


【解决方案1】:

使用Dictionary&lt;ScheduleTableKey, double&gt;(假设值为double 类型),其中ScheduleTableKey 是由所有键列组成的结构。您将获得接近 O(1) 的复杂度。

例如:

struct ScheduleTableKey {
    DateTime Date;
    string   Location;
    string   Schedule_Id;
    string   Type;
    int?     Lane;
}

var table = new Dictionary<ScheduleTableKey, double>();

请注意,根据您的情况,不同类型的结构成员可能更合适。

【讨论】:

  • 这个结构行不通,因为他有重复。它可能应该是Dictionary&lt;Schedule, List&lt;Double&gt;&gt;,并且总是提到如果您使用自定义类作为字典中的键,该类应该实现IEquatable&lt;T&gt; 并覆盖EqualsGetHashCode()
  • @ErikPhilips 他特别指出,5 列键是唯一的:Schedule 表具有这五个键组合的唯一行
  • 我认为他混淆了命名法unique。他应该只说有一个key,但正如你可以清楚地看到表格的前两行看起来像这样是通过那个键重复的。
  • @ErikPhilips 哦,没注意到。我要求 OP 进行澄清。
  • 谢谢 MartinHeralecký,@ErikPhilips,我的意思是前 5 个键的组合是唯一的,最后两个键可能有空值想知道如果我们创建一个具有前三个属性(日期、位置、 Schedule Id),然后创建具有最后三个关键属性(类型、土地、值)的项目列表。这样,当找到 key 上的记录时,可以执行列表或线性搜索以找到适当的组合。一个问题是要知道构建这样一个字典需要多长时间才能使用它,以及获取单个记录的时间。
【解决方案2】:

Dictionary 将占用所有键和值的存储空间,但只需百分之一秒即可从 40,000 条记录中创建,并且可以让您非常高效地查找值。

假设src 是包含您的日程表的IEnumerable&lt;&gt;,您可以使用

转换为字典
var ValueMap = src.ToDictionary(s => new { s.Date, s.Location, s.ScheduleId, s.Type, s.Lane }, s => s.Value);

然后您可以使用以下方法查找值:

var k = new { Date, Location, ScheduleId, Type, Lane };
var value = ValueMap[k];

如果您不知道调度表中是否存在特定键,您可以使用

if (ValueMap.TryGetValue(k, out var value)) {
    // use value here
}
else {
    // there is no matching value
}

如果可用(例如 C# 7)使用 ValueTuple 将更快地处理并且在进行数百万次查找时不会产生垃圾(如果这很重要)。

var ValueMap = src.ToDictionary(s => (s.Date, s.Location, s.ScheduleId, s.Type, s.Lane), s => s.Value);

var k = (Date, Location, ScheduleId, Type, Lane);
var value = ValueMap[k];

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-08
    • 2018-05-19
    • 2011-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-30
    相关资源
    最近更新 更多