设计MapReduce函数以查找集合列表之间的交集

时间:2018-05-29 00:24:35

标签: hadoop mapreduce set

假设我有多个列表

L1 = [{2,7},{2,7,8},{2,3,6,7},{1,2,4,5,7}]      
L2 = [{3,6},{1,3,4,6,7},{2,3,5,6,8}]      
L3 = [{2,5,7,8},{1,2,3,5,7,8}, {2,4,5,6,7,8}] 

L1,L2和L3的每个元素之间的交集是:

{2,7}.intersection({3,6}).intersection({2,5,7,8})= empty  
{2,7}.intersection({3,6}).intersection({1,2,3,5,7,8})= empty  
{2,7}.intersection({3,6}).intersection({2,4,5,6,7,8})= empty  
{2,7}.intersection({1,3,4,6,7}).intersection({2,5,7,8})= {7}  
{2,7}.intersection({1,3,4,6,7}).intersection({1,2,3,5,7,8})= {7}  
{2,7}.intersection({1,3,4,6,7}).intersection({2,4,5,6,7,8})= {7}
...............................   

如果我们继续这样做,我们最终得到以下集合:

{{empty},{2},{3},{6},{7},{2,3},{2,5},{2,6},{2,8},{3,7},{4,7},{6,7},{1,7}}

假设我有很多列表L1,L2,L3,... Ln。如何设计Map和Reduce函数来计算这些输入列表集之间的交叉点。

请帮忙。我只需要这个想法。

1 个答案:

答案 0 :(得分:0)

这不可能适合单个Map / Reduce作业。我并不认为这个用例通常非常适合M / R范例,因为它似乎并不能很好地并行化并且需要对大量数据进行混洗。

为了简单起见,我只是将输入和运算符转换为更简单的版本,保持其属性不变。假设你有数字和总和的列表(为了我们的目的,这应该是等价的)而不是集合和交集的列表。

所以你想要计算从不同列表中选择的所有可能的数字总和:

输入:

L1: [1, 2, 3]
L2: [4, 5]
L3: [6, 7]

结果:

[
  1+4+6, 1+4+7, 1+5+6, 1+5+7,
  2+4+6, 2+4+7, 2+5+6, 2+5+7,
  3+4+6, 3+4+7, 3+5+6, 3+5+7
]
 = [11, 12, 12, 13, 12, 13, 13, 14, 13, 14, 14, 15]

删除重复项后,您最终会得到:

[11, 12, 13, 14, 15]

检查点:请确认我的要求是正确的。

为了最终计算reducer中的和,每个列表中的每个元素都需要在映射器下输出一些键,这些键等于所有其他列表的长度相乘;并且键需要允许连接减速器中不同列表的所有元素组合。

由于列表的大小不一定相同,因此在评估每个列表记录时,如果知道数据集中每个其他列表的确切长度,则只能确保上述内容。 (此先验知识表示生成长度数组的另一个M / R作业。)然后,您可以通过连接每个可能的元素索引组合来计算密钥。

在我们的示例中,值“1”(在L1中为索引0)将在以下键下发出:"000"(即1+4+6),"001",{ {1}},"010"(探索从'1'到其余列表的所有可能路径)。对于值“7”(L3中的索引1),我们将:"011""001""011""101""111",{{1 }}

一旦你这样做了,你最终会在减速器中输入相同键下的数字(这正是你想要的,除了你在这个阶段还有重复的总和):

"201"

但这是一个很多数据要洗牌!当然,您也可以使用reducer作为合并器,但仍然:使用大小为M的N个列表,您将在每个列表中发出M ^ N次的元素。我假设N是数百万(至少),否则你不会考虑map / reduce。 此外,您从map输出的每个键都将是一个长度为N的字符串(数据集中的列表数)。因此,您可以轻松地使用MB大小的键(即使您切换到更紧凑的二进制格式)。

要实现这一点,您需要一个先决条件作业来计算列表大小数组,最后,重复数据删除可能还需要另一个作业(除非您正在写一些为您执行此操作的存储空间)。

总而言之,必须有更好的方法...... 如果您的数据集适合单个节点的内存,请尝试一下。你正在计算的交叉点会自然地缩小范围(如果你很幸运的话),大多数交叉点最终会以空集的速度结束。