根据元组

时间:2017-02-01 06:15:08

标签: python list random duplicates tuples

有没有办法根据元组中的索引删除重复的元组。说我有

[(0, 4, 1.0), (1, 4, 1.0), (3, 4, 1.0), (0, 3, 2.0), (1, 3, 2.0), (0, 2, 3.0), (1, 2, 3.0), (2, 4, 4.0), (2, 3, 5.0), (0, 1, inf)]

我可以随机保留一个元组,其中每个副本在索引2处具有相同的值吗?

因此,有3个元组在索引2处具有值1.0,两个元组在索引2处具有值2.0,一个在索引2处具有值3,依此类推。

因此,可以从索引2处的值1.0中随机选择(0,4,1.0),并且可以从索引2处的值2.0中随机选择(1,3,2.0)。 比如说,(1,2,3.0)是从索引2处的值3.0中随机选择的。 然后,我的列表看起来像

[(0, 4, 1.0),(1, 3, 2.0), (1, 2, 3.0), (2, 4, 4.0), (2, 3, 5.0), (0, 1, inf)]

我从未遇到过这样或至少有效的功能。

2 个答案:

答案 0 :(得分:5)

您可以使用itertools.groupby根据索引2处的值对元组进行分组。然后,对于每个组,您可以使用random.choice来选择元组:

>>> from itertools import groupby
>>> import random
>>> l = [(0, 4, 1.0), (1, 4, 1.0), (3, 4, 1.0), (0, 3, 2.0), (1, 3, 2.0), (0, 2, 3.0), (1, 2, 3.0), (2, 4, 4.0), (2, 3, 5.0), (0, 1, float('inf'))]
>>> [random.choice(tuple(g)) for _, g in groupby(l, key=lambda x: x[2])]
[(1, 4, 1.0), (1, 3, 2.0), (1, 2, 3.0), (2, 4, 4.0), (2, 3, 5.0), (0, 1, inf)]

在上面的groupby中返回可迭代的(key, group)元组,其中key是由赋予groupby的第二个参数返回的值,而group是组中元素的可迭代:

>>> [(k, tuple(g)) for k, g in groupby(l, key=lambda x: x[2])]
[(1.0, ((0, 4, 1.0), (1, 4, 1.0), (3, 4, 1.0))), (2.0, ((0, 3, 2.0), (1, 3, 2.0))), (3.0, ((0, 2, 3.0), (1, 2, 3.0))), (4.0, ((2, 4, 4.0),)), (5.0, ((2, 3, 5.0),)), (inf, ((0, 1, inf),))]

由于我们不需要密钥,我们可以将其丢弃并将组转换为random.choice预期的序列:

>>> [random.choice(tuple(g)) for _, g in groupby(l, key=lambda x: x[2])]
[(1, 4, 1.0), (1, 3, 2.0), (0, 2, 3.0), (2, 4, 4.0), (2, 3, 5.0), (0, 1, inf)]

请注意,上面预期索引2处具有相同值的元组在输入中彼此相邻。如果情况并非如此,您可以在将原始列表传递给groupby之前对其进行相应排序。

更新如果您只想要结果的三个第一个值,则可以使用生成器表达式而不是列表推导,并使用islice从那里拉出值:

>>> from itertools import islice
>>> gen = (random.choice(tuple(g)) for _, g in groupby(l, key=lambda x: x[2]))
>>> list(islice(gen, 3))
[(0, 4, 1.0), (1, 3, 2.0), (0, 2, 3.0)]

答案 1 :(得分:0)

我不会在一次操作中这样做,但我相信它是可能的。

我首先会为索引2的每个值创建一个列表:

values_at_index_2 = {t[2] for t in data}
groups_by_value = [[t for t in data if t[2] == v] for v in values_at_index_2]

然后在每个组中选择一个元组:

import random
new_data = [random.choice(group) for group in groups_by_value]