首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >处理一组独特的元组

处理一组独特的元组
EN

Stack Overflow用户
提问于 2013-11-05 22:36:59
回答 3查看 124关注 0票数 1

我有一组独特的元组,如下所示。第一个值是名称,第二个值是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”)

任何帮助都是非常感谢的!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2013-11-05 22:46:31

itertools.groupby将对其输出的内容进行一些附加处理,以完成以下工作:

代码语言:javascript
复制
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))

产出:

代码语言:javascript
复制
('10', '0000007', 'PBM', 'IBL')
('12', '0000051', 'LRA', 'PBL')
('7', '0000014', 'LRA', 'PBL', 'IBL')
('9', '0000022', 'LRA', 'PBL', 'IBL')

P.S.,但我不太喜欢这个设计: thet类型可以/应该是包含在元组的第三项中的列表,而不是元组本身的一部分.因为这样的话元组的长度是动态的,而且很难看.元组不应该像那样使用。所以最好换掉

代码语言:javascript
复制
        types = tuple(type_ for _, _, type_ in items)
        yield (name, id_) + types

使用

代码语言:javascript
复制
        types = [type_ for _, _, type_ in items]
        yield (name, id_, types)

让你看起来更干净

代码语言:javascript
复制
('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:迭代生成的数据。

票数 3
EN

Stack Overflow用户

发布于 2013-11-05 23:09:28

使用defaultdict进行积累并进行筛选非常简单:

代码语言:javascript
复制
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']})

然后过滤:

代码语言:javascript
复制
[(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'])]

如果你真的想让它回到原来的格式:

代码语言:javascript
复制
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是最有意义的,就像我们在第一步中生成的那样。

票数 1
EN

Stack Overflow用户

发布于 2013-11-05 23:12:55

科学的一条线(其他的答案更易读,可能更正确):

代码语言:javascript
复制
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

产量:

代码语言:javascript
复制
[('9', '0000022', 'LRA', 'PBL', 'IBL'),
 ('12', '0000051', 'LRA', 'PBL'), 
 ('10', '0000007', 'PBM', 'IBL'), 
 ('7', '0000014', 'IBL', 'PBL', 'LRA')]
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19800454

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档