我有一组独特的元组,如下所示。第一个值是名称,第二个值是ID,第三个值是类型。
(“9”、“0000022”、“上帝军”) (“45”、“0000016”、“PBM”) (“16”,“0000048”,“PBL”) (“304”、“0000042”、“PBL”) (“7”,“0000014”,“IBL”) (“12”、“0000051”、“上帝军”) (“7”,“0000014”,“PBL”) (“68”、“0000002”、“PBM”) ('356','0000049','PBL') (“12”,“0000051”,“PBL”) (“15”,“0000015”,“PBL”) (“32”,“0000046”,“PBL”) (“9”,“0000022”,“PBL”) ('10','0000007','PBM') (“7”、“0000014”、“上帝抵抗军”) (“439”、“0000005”、“PBL”) (“4”、“0000029”、“上帝军”) (“41”,“0000064”,“PBL”) (“10”,“0000007”,“IBL”) (“8”,“0000006”,“PBL”) (“331”、“0000040”、“PBL”) (“9”,“0000022”,“IBL”)
此集合包括名称/ID组合的重复项,但它们都有不同的类型。例如:
(“9”、“0000022”、“上帝军”) (“9”,“0000022”,“PBL”) (“9”,“0000022”,“IBL”)
我想做的是处理这组元组,以便创建一个新列表,其中每个名称/ID组合只出现一次,但包含所有类型。此列表只应包括具有多个类型的名称/ID组合。例如,我的输出如下所示:
(“9”,“0000022”,“上帝军”,“PBL”,“IBL”) (“7”、“0000014”、“IBL”、“PBL”、“上帝军”)
但是,我的输出不应该包括只有一种类型的名称/ID组合:
(“45”、“0000016”、“PBM”) (“16”,“0000048”,“PBL”)
任何帮助都是非常感谢的!
发布于 2013-11-05 22:46:31
itertools.groupby将对其输出的内容进行一些附加处理,以完成以下工作:
from itertools import groupby
data = {
('9', '0000022', 'LRA'),
('45', '0000016', 'PBM'),
('16', '0000048', 'PBL'),
...
}
def group_by_name_and_id(s):
grouped = groupby(sorted(s), key=lambda (name, id_, type_): (name_, id))
for (name, id_), items in grouped:
types = tuple(type_ for _, _, type_ in items)
if len(types) > 1:
yield (name, id_) + types
print '\n'.join(str(x) for x in group_by_name_and_id(data))产出:
('10', '0000007', 'PBM', 'IBL')
('12', '0000051', 'LRA', 'PBL')
('7', '0000014', 'LRA', 'PBL', 'IBL')
('9', '0000022', 'LRA', 'PBL', 'IBL')P.S.,但我不太喜欢这个设计: thet类型可以/应该是包含在元组的第三项中的列表,而不是元组本身的一部分.因为这样的话元组的长度是动态的,而且很难看.元组不应该像那样使用。所以最好换掉
types = tuple(type_ for _, _, type_ in items)
yield (name, id_) + types使用
types = [type_ for _, _, type_ in items]
yield (name, id_, types)让你看起来更干净
('10', '0000007', ['IBL', 'PBM'])
('12', '0000051', ['LRA', 'PBL'])
('7', '0000014', ['IBL', 'LRA', 'PBL'])
('9', '0000022', ['IBL', 'LRA', 'PBL'])例如,您可以使用for name, id, types in transformed_data:迭代生成的数据。
发布于 2013-11-05 23:09:28
使用defaultdict进行积累并进行筛选非常简单:
from collections import defaultdict
d = defaultdict(list)
for tup in list_of_tuples:
d[(tup[0],tup[1])].append(tup[2])
d
Out[15]: defaultdict(<class 'list'>, {('16', '0000048'): ['PBL'], ('9', '0000022'): ['LRA', 'PBL', 'IBL'], ('12', '0000051'): ['LRA', 'PBL'], ('304', '0000042'): ['PBL'], ('331', '0000040'): ['PBL'], ('41', '0000064'): ['PBL'], ('356', '0000049'): ['PBL'], ('15', '0000015'): ['PBL'], ('8', '0000006'): ['PBL'], ('4', '0000029'): ['LRA'], ('7', '0000014'): ['IBL', 'PBL', 'LRA'], ('32', '0000046'): ['PBL'], ('68', '0000002'): ['PBM'], ('439', '0000005'): ['PBL'], ('10', '0000007'): ['PBM', 'IBL'], ('45', '0000016'): ['PBM']})然后过滤:
[(key,val) for key,val in d.items() if len(val) > 1]
Out[29]:
[(('9', '0000022'), ['LRA', 'PBL', 'IBL']),
(('12', '0000051'), ['LRA', 'PBL']),
(('7', '0000014'), ['IBL', 'PBL', 'LRA']),
(('10', '0000007'), ['PBM', 'IBL'])]如果你真的想让它回到原来的格式:
from itertools import chain
[tuple(chain.from_iterable(tup)) for tup in d.items() if len(tup[1]) > 1]
Out[27]:
[('9', '0000022', 'LRA', 'PBL', 'IBL'),
('12', '0000051', 'LRA', 'PBL'),
('7', '0000014', 'IBL', 'PBL', 'LRA'),
('10', '0000007', 'PBM', 'IBL')]尽管我认为保留它为一个以(name,id)元组作为键的dict是最有意义的,就像我们在第一步中生成的那样。
发布于 2013-11-05 23:12:55
科学的一条线(其他的答案更易读,可能更正确):
testlist=[('9', '0000022', 'LRA'),
('45', '0000016', 'PBM'),
('16', '0000048', 'PBL'),
('304', '0000042', 'PBL'),etc.]
from collections import Counter
new_list = [(a1,b1)+tuple([c for (a,b,c) in testlist if (a,b) == (a1,b1)]) \
for (a1,b1) in [pair for pair,count in Counter([(a,b) \
for (a,b,c) in testlist]).iteritems() if count > 1]]
print new_list产量:
[('9', '0000022', 'LRA', 'PBL', 'IBL'),
('12', '0000051', 'LRA', 'PBL'),
('10', '0000007', 'PBM', 'IBL'),
('7', '0000014', 'IBL', 'PBL', 'LRA')]https://stackoverflow.com/questions/19800454
复制相似问题