2

我有一本字典,对于每个键,我都有一个元组列表。列表的长度各不相同,但每个元组都有 4 个条目。这是一键的示例

genes = {'Tcea1': [
('995', '057', '551', '613'), 
('825', '912', '541', '683'), 
('541', '683', '821', '877'), 
('825', '912', '538', '683'), 
('538', '683', '821', '877'), 
('489', '584', '551', '613')]}

我想做的是删除重复项。但我唯一关心的部分是索引位置 1 和 2。所以在上面的例子中我想要 ('541', '683', '821', '877') 和 ('538', '683', ' 821', '877') 已删除,因为索引 1 对于两者都是 683,而索引 2 对于两者都是 821。所以理想的输出是

genes = {'Tcea1': [
('995', '057', '551', '613'), 
('825', '912', '541', '683'), 
('825', '912', '538', '683'), 
('489', '584', '551', '613')]}

这让我很难过。下面是我能得到的最接近的。以下代码将仅删除其中一个元组,但我希望两者都消失

seen = set()
seen_add = seen.add
genes['Tcea1'] = [x for x in genes['Tcea1'] if tuple(x[1:3]) not in seen and not seen_add(tuple(x[1:3]))]

编辑:我需要保持秩序

4

4 回答 4

4

您可以执行以下操作:

from collections import Counter

def selectUnique(x):
    count = Counter((i[1], i[2]) for i in x)
    out = [i for i in x if count[(i[1], i[2])] == 1]
    return out

计数器只是将键映射到频率的字典。

于 2013-09-04T21:25:43.007 回答
1

您可以使用Counter来检测重复项,然后根据它进行过滤:

from collections import Counter
def myfilter(list_of_tuples):
  key = lambda tpl: tpl[1:3]
  counter = Counter(key(t) for t in list_of_tuples)
  return [ t for t in list_of_tuples if counter[key(t)] <= 1 ]

并像这样适用于您的字典:

new_genes = { k: myfilter(v) for k,v in genes.items() }

该解决方案还保持秩序。

于 2013-09-04T21:26:27.117 回答
1

最短的解决方案是

    { k: [ a for a in genes[k] if len([ b for b in genes[k] if b[1:3] == a[1:3]  ]) < 2  ] for k in genes }

如果列表相对较短应该很好。

于 2013-09-04T21:57:30.913 回答
0

在我看来这是最简单的方法

>>> from collections import Counter
>>> counter = Counter(x[1:3] for x in genes['Tcea1'])
>>> filter(lambda x: counter[x[1:3]] == 1, genes['Tcea1'])
[('995', '057', '551', '613'), ('825', '912', '541', '683'), ('825', '912', '538', '683'), ('489', '584', '551', '613')]
于 2013-09-04T21:31:25.757 回答