我有Dictionary<string,T>
其中string表示记录的关键字,我还有两条关于我需要为字典中的每条记录维护的记录的信息,它们是记录的类别及其冗余(重复多少次)。
例如:记录XYZ1属于类别1,并且重复1次。因此实现必须是这样的:
"XYZ1", {1,1}
现在继续,我可能会在我的数据集中遇到相同的记录,因此密钥的值必须更新如下:
"XYZ1", {1,2}
"XYZ1", {1,3}
...
由于我正在处理大量的记录,例如100K,我尝试了这种方法,但它看起来效率低下,因为从字典中获取值然后切片{1,1}
然后将两个切片转换为整数的额外工作会很多执行的开销。
我正在考虑使用二进制数字来表示类别和重新定位,也可能使用位掩码来获取这些部分。
修改:我尝试将对象与2个属性一起使用,然后再使用Tuple<int,int>
。复杂性变得更糟!
我的问题:是否可以这样做?
如果不是(就复杂性而言)有任何建议吗?
答案 0 :(得分:0)
似乎类别永远不会改变。因此,我不会使用简单的字符串作为字典的键,而是执行以下操作:
Dictionary<Tuple<string,int>,int>
其中字典的键是Tuple<string,int>
,其中string
是记录,int
是类别。然后字典中的值只是一个计数。
字典很可能是你要完成的最快的数据结构,因为它几乎有一定的时间O(1)查找和输入。
您可以使用元组加快一点,因为现在该类别是密钥的一部分,而不再是您必须单独访问的一些信息。
同时您还可以将字符串作为键并将Tuple<int,int>
作为值存储,只需将Item1
设置为类别,将Item2
设置为计数。
无论哪种方式都与速度大致相同。以这种方式处理100k记录应该非常快。
答案 1 :(得分:0)
您的类型T
是什么?您可以定义一个自定义类型,其中包含您需要的信息(类别和出现)。
class MyInfo {
public int c { get; set; }
public int o { get; set; }
}
Dictionary<String, MyInfo> data;
然后,当遍历您的数据时,您可以轻松检查某些密钥是否已存在。如果是,只需增加出现次数,否则插入一个新元素。
MyInfo d;
foreach (var e in elements) {
if (!data.TryGet(e.key, out d))
data.Add(e.key, new MyInfo { c = e.cat, o= 1});
else
d.o++;
}
修改
您还可以将类别和出现次数合并到一个UInt64中。例如,取较高32位的类别(即可以有40亿个类别)和较低32位的发生次数(即每个键可以出现40亿次)
Dictionary<string, UInt64> data;
UInt64 d;
foreach (var e in elements) {
if (!data.TryGet(e.key, out d))
data[e.key] = (e.cat << 32) + 1;
else
data[e.key] = d + 1;
}
如果您想获得一个特定键的出现次数,您可以只检查该值的相应部分。
var d = data["somekey"];
var occurrences = d & 0xFFFFFFFF;
var category = d >> 32;