对于这些类型的问题,您需要了解某些算法的扩展性比其他算法更好,并且任何一种算法的性能都取决于数据的“形状”和大小。
将每个用户的项目集与每个其他用户进行比较可能适用于小型域数据集(比如 1000 个或用户,甚至可能是 10,000 个,具有相似数量的项目),但这是一个“n 平方”问题(或订单至少可以说,我的大 O 生锈了!):
Users Comparisons
----- -----------
2 1
3 3
4 6
5 10
6 15
n (n^2 - n)/2
因此,100,000 个用户域将产生 4,999,950,000 组比较。
解决此问题的另一种方法是反转关系,因此运行 Map Reduce 作业以生成用户的项目映射:
'a' : [ 'u1', 'u2', 'u3' ],
'b' : [ 'u2' ],
'c' : [ 'u1' ],
'f' : [ 'u2', 'u3' ],
'h' : [ 'u1' ],
从那里您可以迭代每个项目的用户并输出用户对(计数为 1):
'a' would produce: [ 'u1_u2' : 1, 'u1_u3' : 1, 'u2_u3' : 1 ]
'f' would produce: [ 'u2_u3' : 1 ]
然后最终产生每个用户配对的总和:
[ 'u1_u2' : 1, 'u1_u3' : 1, 'u2_u3' : 2 ]
这不会产生您感兴趣的行为(u1 和 u3 项目集中的双 a),但会详细说明初始实现。
如果您知道您的域集通常包含没有共同项目的用户、每个用户的少量项目或具有大量不同值的项目域,那么此算法将更有效(之前您正在比较每个用户到另一个用户,两组之间的交叉概率很低)。我相信数学家可以为你证明这一点,但我不是!
这也有与以前相同的潜在扩展问题——如果你有一个所有 100,000 个用户都共有的项目,你仍然需要生成 40 亿个用户对。这就是为什么在盲目地对数据应用算法之前了解数据很重要的原因。