有没有办法根据元组中的索引删除重复的元组。说我有
[(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)]
我从未遇到过这样或至少有效的功能。
答案 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]