我有一个接收三个不同“人”对象的函数,并根据“people”对象中的组合值生成一个新的“兼容性”对象。
然而,作为输入接收的三个“人”对象的大约1/3的时间与之前的一个相同,尽管可能以不同的顺序。在这些情况下,我不想创建一个新的“得分”对象,而只是返回现有对象中包含的值。
最初,程序只是遍历列表<> “兼容性”对象搜索属于这三个“人”的对象(因为每个“兼容性”对象包含一个人对象数组)。考虑到有超过数千个“兼容性”对象和超过一百万“人”对象,这种方法非常慢。
我想到了使用字典,其中键是我通过使用XOR将三个人对象的id值组合成单个UInt64而生成的数字,并将得分对象存储为字典值而不是列表。这样可以将时间缩短一半左右,并且在时间性能方面是可以接受的,但是碰撞太多了,并且它会经常返回错误的分数。
非常感谢任何建议或指示。
编辑:要添加到原始问题,每个“people”对象都有一堆我可以使用的其他字段,但问题是制作一个UNIQUE和COMMUTATIVE的键。
答案 0 :(得分:5)
我认为你是以过于复杂的方式看待事物。获取3个PersonID值并对它们进行排序,这样它们总是处于相同的顺序,无论它们传入的顺序如何。然后使用三个PersonID作为键在一个哈希表中设置一个值,用连字符或一些分隔PersonID值中不会出现的其他字符。然后,检查哈希表中是否有一个带有该键的值。
因此,如果三个PersonID分别为10,5和22,则哈希键可能类似于“5-10-22”。
答案 1 :(得分:1)
在按预先确定的顺序对三重奏进行排序后,通过连接对象ID来创建密钥。
答案 2 :(得分:0)
您最好的选择是自定义IEqualityComparer
课程。声明你的Dictionary
就像这样
Dictionary<List<People>, Compatability> people =
new Dictionary<List<People>, Compatability>(new PersonListComparer());
您需要创建一个实现PersonListComparer
的{{1}}类。您需要实现两种方法,一种是获取哈希码,另一种是比较相等性。 IEqualityComparer<List<People>>
将使用Dictionary
来确定两个列表是否可能相等,并使用GetHashCode
方法来确定它们是否实际存在(换句话说,哈希码很快但可以给出一个误报但绝不是假阴性)。对Equals
使用现有的哈希算法(XOR),然后在GetHashCode
方法中明确地对两个列表进行共处。
这应该可以解决问题!
答案 3 :(得分:0)
为什么不使用人名作为字典键? (首先对名称进行排序,以便传递顺序无关紧要。) IE,John,Alice和Bob变得类似于my_dictionary [“Alice_Bob_John”]&lt; - 如果该密钥存在,您已经计算了分数,否则,您需要计算它。作为上面的字符串黑客的替代方法,您实际上可以使用结构:
NameTriple n = new NameTriple("John", "Alice", "Bob");
// NameTriple internally sorts the names.
my_dictionary[n] ...
答案 4 :(得分:0)
如果您想将所有内容保存在内存中而不使用数据库,我建议使用类似于树结构的内容。假设您的对象ID是可排序的并且顺序无关紧要,您可以使用嵌套字典来完成此操作。
即Dictionary<Key, Dictionary<Key, Dictionary<Key, Compatibility>>>
应该做的伎俩。对ID进行排序,并使用外部字典中的最小值,下一个值中的下一个值以及查找兼容性对象的最终值。这样,就不会发生冲突,查找应该非常快。
或者,现在我再想一想,这并不是那么复杂。只需使用字符串作为键,并按照排序顺序将ID连接在一起,并使用“!”或者介于两者之间的其他内容在ID中不会自然发生。
答案 5 :(得分:0)
假设所有“Person”对象都是唯一的,则在对象中存储UUID。
在您的函数中静态存储四元组(P1,P2,P3,V),其中P1,P2,P3是Person对象的UUID,排序(以避免排序问题),V是上一次计算的结果。
然后你的函数检查是否有这个三重人员的条目,如果没有,它会完成工作并存储它。
你可以将(P1,P2,P3,V)值存储在字典中,只需关闭三个P值的一些哈希值