散列对象集C#

时间:2012-10-19 15:30:35

标签: c# hash

我有多个订单,每个订单都包含已购买的Item个对象。

1 : {Item1, Item2, Item3, Item4, Item5}  
2 : {Item2, Item8, Item4, Item3, Item11, Item5} 
3 : { ... }

我的目标是确定每个项目的购买频率,并能够在O(1)中获得结果。

我的想法是迭代订单,基于子集项 - 增加特定数组的元素。这将为我提供在O(1)中提取所需值的可能性。

EG。 Item3和Item4被买了2次。

int frequency = myArray[getHash(Item3+Item4)]

print frequency;

Output : 2

问题:

开发一个int getHash(...)函数,它可以对项目的子集进行哈希处理。

注意:{Item1,Item2} = {Item2,Item1}

非常感谢!欢迎任何更好的想法的帮助!

2 个答案:

答案 0 :(得分:4)

因为{A,B} = {B,A}您首先需要在继续之前对列表进行排序。您排序的并不重要,但您确实需要确保没有任何值被视为排序目的,除非它们在排序中可以互换。

接下来,任何简单的哈希算法都应该有效。一种常见的技巧是使用两个素数,我称之为cp

int hash = c;
foreach(Item i in items) hash = hash * p + i.GetHashCode()
return hash;

p有时被选为31,因为它不仅是素数,而且编译器将其解析为比特移位和减法,这比乘法快得多。 x * 31(x << 5) - 1相同(假设我使用了正确的班次......我不时搞砸了,哈哈。)

答案 1 :(得分:0)

对不起,我没有使用哈希,但是我试着以一种我想做的方式试一试。就像试图解决这种挑战一样。

Dictionary<Item, Dictionary<Item, Count>> combine = new Dictionary<Item, Dictionary<Item, Count>>();

foreach (Item item in Sell)
{
    Dictionary<Item, int> key;
    if (!combine.TryGetValue(item, out key))
    {
        key = new Dictionary<Item, Count>();
        combine.Add(item, key);
    }

    foreach (Item otherItem in Sell)
    {
        if (item == otherItem)
            continue;

        Count count;
        if (key.TryGetValue(otherItem, out count))
            count++;
        else
            key.Add(otherItem, new Count());
    }
}

这可能是非常愚蠢的,因为对于每个项目,你最后都会得到一个同时用柜台购买的所有其他物品的字典。如果你想知道Item1是否与Item2 AND Item3和Item2 OR Item3 ...... Bleh同时购买。没关系。