快速迭代字典(string, List>)

本文关键字:List string 迭代 字典 | 更新日期: 2023-09-27 17:50:51

我有一个150万条记录的列表。我需要迭代这个列表大约300次,以取出某些记录进行计算。我假设将List转换为Dictionary将使我的查找在迭代过程中更快。

My List由这样一个类组成:

class SummaryRecord
{
    public int CalcData { get; set; }
    public string Id2 { get; set; }
    public string Id2 { get; set; }
}

因为我有两个id,使记录唯一,我把我的列表转换为字典,像这样:

Dictionary<string, SummaryRecord> dictSummaries = summaries.ToDictionary(
    e => e.Id1 + "+" + e.Id2 + "+" + e.CalcData);

然后循环遍历包含300个ID对的二级列表,从大列表中取出记录。

foreach(var ids in listOfIds)
{
    var filteredData = from d in dictSummaries
                       where
                       d.Key.Contains(ids.Id1 + "+" + ids.Id2)
                       select d;
    //perform operation on filteredData here. This code is slow as well.
    filteredData.Count()
}

根据我所看到的性能,这显然不是很有效,因为执行每次迭代需要大约1秒(乘以300秒)。如何加快查询记录的过程?

快速迭代字典(string, List>)

实际上,您并没有使用字典的功能。查询将遍历字典中的每条记录,检查您给出的条件。

由于您有完整的键,您应该直接查找每个键:

string key = ids.Id1 + "+" + ids.Id2; SummaryRecord summaryRecord = dictSummaries[key];

如果您不确定该键是否存在,请确保执行TryGetValue()或ContainsKey()检查。

既然你使用3个字段作为你的字典的键

摘要。ToDictionary (e => e. id1 +" +" + e. id2 +" +" + e. calcdata);

我相信有可能有倍数,id1+id2。如果是这种情况,你可以使用ToLookup,而不是ToDictionary。

var lookup = summaries.ToLookup(e => e.Id1 + "+" + e.Id2);

foreach(var ids in listOfIds)
{
    var filteredData = lookup[ids.Id1 + "+" + ids.Id2];
    //perform operation on filteredData here. This code is slow as well.
    filteredData.Count()
}

现在如果不可能有多个id1 + id2,为什么你连接id1 + id2 + CalcData?

很确定你正在调用String.Contains.
您正在迭代字典中的每个键并测试键是否包含另一个字符串。
所以"prekey1key2"包含"key1key2 "
如果你想获得一个精确的查找,请注意这不是你得到的(而且你根本没有使用Dictionary hashbucket)。

您正在迭代每个记录。您根本没有使用字典查找。更糟糕的是,您要为listOfIds中的每一行迭代Dictionary中的每条记录。

如果ID1和ID2形成一个唯一的键,那么使用它作为键并直接查找它,就像Kevin的答案一样
这是哈希查找,非常快

SummaryRecord summaryRecord = dictSummaries[key];

也选择散列好的ID1, ID2。
你能用两个int16组合成一个Int32吗?
你可以用真正的键来重写GetHashCode。
重写Equals。

另一种处理方式

class SummaryRecord
{
    public int CalcData { get; set; }
    public string Key { get { return Id1 + Id2; } 
    public string Id2 { get; set; }
    public string Id2 { get; set; }
}
private HashSet<String> keyToFind = new  HashSet<String>() {"key1","key2"}; 
var filteredData = from d in dictSummaries.where(x => keyToFind.Contains(x.key));

That Contains将是一个HashBucket查找。
你仍然在迭代字典,但现在你有了一个非常有效的比较。
这里的好处是你只迭代字典一次。
先试试这个。