DeleteDuplicates同时保留子列表结构

时间:2012-02-16 21:05:41

标签: list wolfram-mathematica filtering

我想从列表列表中删除重复数据删除,保持子列表结构不变。

E.g。

{{1, 7, 8}, {4, 3}, {4, 1, 9}, {9, 2}}

变为

{{1, 7, 8}, {4, 3}, {9}, {2}}

这是嵌套的范围,空的子列表是可以的。

3 个答案:

答案 0 :(得分:11)

这是一个经典的伎俩:

list = {{1, 7, 8}, {4, 3}, {4, 1, 9}, {9, 2}}

Module[{f},
 f[x_] := (f[x] = Sequence[]; x);
 Map[f, list, {2}]
]

要了解它是如何工作的,请考虑第一次评估f[1]时会发生什么。 f[1]将评估为(f[1]=Sequence[]); 1,然后评估为1。所以现在已经为f[1]做了定义。下次评估f[1]时,它只会评估为Sequence[]

因此,第一次为参数计算f时,它返回该参数。评估它的第二个(或第三个等)时间,它返回Sequence[]Sequence[]具有完全从表达式中删除的属性,即{1, Sequence[], 3}将评估为{1, 3}

总而言之,该函数的作用是:第一次看到一个元素时,它会将元素替换为自身(单独留下)。第二次它看到相同的元素,它会删除它。我将此函数映射到“level 2”,因此它仅对子列表的元素起作用。

答案 1 :(得分:3)

您可以使用Complement进行此操作,您唯一需要做的就是存储您已经看过的所有元素。在开始时,所有看到的元素a的列表为空,然后逐步添加子列表中的所有数字。每个步骤都使用此累积列表来删除已经看过的所有数字:

DeleteDuplicatesList[l_List] :=
  Block[{a = {}},
   Table[With[{b = a},
     a = Union[a, c];
     Complement[c, b]], {c, l}]
   ];

l = {{1, 7, 8}, {4, 3}, {4, 1, 9}, {9, 2}};
DeleteDuplicatesList[l]

答案 2 :(得分:2)

它并不优雅,但它完成了工作:

t = {{1, 7, 8}, {4, 3}, {4, 1, 9}, {9, 2}}; 

Delete[t, Flatten[Rest[Position[t, #]] & /@ (DeleteDuplicates[Flatten[t]]), 1]]

DeleteDuplicates ...将返回t中的数字集,而不是多集。 Rest[Position[ ...将返回重复的位置。 Delete删除了所说的副本。