假设我有多个列表
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函数来计算这些输入列表集之间的交叉点。
请帮忙。我只需要这个想法。
答案 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大小的键(即使您切换到更紧凑的二进制格式)。
要实现这一点,您需要一个先决条件作业来计算列表大小数组,最后,重复数据删除可能还需要另一个作业(除非您正在写一些为您执行此操作的存储空间)。
总而言之,必须有更好的方法...... 如果您的数据集适合单个节点的内存,请尝试一下。你正在计算的交叉点会自然地缩小范围(如果你很幸运的话),大多数交叉点最终会以空集的速度结束。