以二进制代码

时间:2016-04-01 20:12:50

标签: c# dictionary binary bitmask

我有Dictionary<string,T>其中string表示记录的关键字,我还有两条关于我需要为字典中的每条记录维护的记录的信息,它们是记录的类别及其冗余(重复多少次)。

例如:记录XYZ1属于类别1,并且重复1次。因此实现必须是这样的:

"XYZ1", {1,1}

现在继续,我可能会在我的数据集中遇到相同的记录,因此密钥的值必须更新如下:

"XYZ1", {1,2} "XYZ1", {1,3} ...

由于我正在处理大量的记录,例如100K,我尝试了这种方法,但它看起来效率低下,因为从字典中获取值然后切片{1,1}然后将两个切片转换为整数的额外工作会很多执行的开销。

我正在考虑使用二进制数字来表示类别和重新定位,也可能使用位掩码来获取这些部分。

修改:我尝试将对象与2个属性一起使用,然后再使用Tuple<int,int>。复杂性变得更糟!

我的问题:是否可以这样做?

如果不是(就复杂性而言)有任何建议吗?

2 个答案:

答案 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;