快速迭代字典(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 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查找。
你仍然在迭代字典,但现在你有了一个非常有效的比较。
这里的好处是你只迭代字典一次。
先试试这个。