【问题标题】:How to merge two tuples in a list if the first tuple elements match?如果第一个元组元素匹配,如何合并列表中的两个元组?
【发布时间】:2015-05-03 01:33:27
【问题描述】:

我有两个形式的元组列表:

playerinfo = [(ansonca01,4,1871,1,RC1),(forceda01,44,1871,1,WS3),(mathebo01,68,1871,1,FW1)]

idmatch = [(ansonca01,Anson,Cap,05/06/1871),(aaroh101,Aaron,Hank,04/13/1954),(aarot101,Aaron,Tommie,04/10/1962)]

我想知道的是如何遍历这两个列表,如果“playerinfo”中的元组中的第一个元素与“idmatch”中的元组中的第一个元素匹配,则将匹配的元组合并在一起以产生一个新的元组列表?形式:

merged_data = [(ansonca01,4,1871,1,RC1, Anson,Cap,05/06/1871),(...),(...), etc.] 

新的元组列表的 ID 号将与正确玩家的名字和姓氏相匹配。

背景信息:我正在尝试合并两个棒球统计数据的 CSV 文档,但包含所有相关统计数据的文档不包含球员姓名,仅包含参考编号,例如'ansoc101',而第二个文档的一列包含参考编号,另一列包含相应玩家的名字和姓氏。

CSV 的大小太大,无法手动执行此操作(大约 20,000 名玩家),因此我正在尝试自动执行此过程。

【问题讨论】:

  • 元组是不可变的;您无法在构造后更改它们包含的变量。我只会使用列表列表,甚至更好的是对象列表或单个对象,其中键是 id 号。

标签: python list csv tuples


【解决方案1】:

使用列表推导来迭代您的列表:

[x + y[1:] for x in list1 for y in list2 if x[0] == y[0]]

我在列表上试过这个:

list1 = [("this", 1, 2, 3), ("that", 1, 2, 3), ("other", 1, 2, 3)]
list2 = [("this", 5, 6, 7), ("that", 10, 11, 12), ("notother", 1, 2, 3)]

得到:

[('this', 1, 2, 3, 5, 6, 7), ('that', 1, 2, 3, 10, 11, 12)]

这是你想要的吗?

【讨论】:

  • 其实这个解决方案虽然简洁,但效率很低。我忘了你说你正在处理大约 20,000 个项目。这种理解会进行 20,000 x 20,000 次比较,即太多了。使用字典的其他解决方案对于大型数据集要好得多
【解决方案2】:

您可以首先创建一个字典以启用快速 ID 号查找,然后使用列表推导非常有效地将两个列表中的数据合并在一起:

import operator

playerinfo = [('ansonca01', 4, 1871, 1, 'RC1'),
              ('forceda01', 44, 1871, 1, 'WS3'),
              ('mathebo01', 68, 1871, 1, 'FW1')]

idmatch = [('ansonca01', 'Anson', 'Cap', '05/06/1871'),
           ('aaroh101', 'Aaron', 'Hank', '04/13/1954'),
           ('aarot101', 'Aaron', 'Tommie', '04/10/1962')]

id = operator.itemgetter(0)  # To get id field.

idinfo = {id(rec): rec[1:] for rec in idmatch}  # Dict for fast look-ups.

merged = [info + idinfo[id(info)] for info in playerinfo if id(info) in idinfo]

print(merged) # -> [('ansonca01', 4, 1871, 1, 'RC1', 'Anson', 'Cap', '05/06/1871')]

【讨论】:

    【解决方案3】:

    字典

    1. 迭代playerinfo 列表并创建字典,其中键是元组中的第一项,值是所有项的列表。
    2. 打印第一步的结果。
    3. 再次迭代idmatch 列表并检查结果字典中元组的第一项是否存在。如果存在,则通过列表扩展方法使用新值扩展键的值。
    4. 打印第二步的结果。
    5. 根据生成的字典创建输出格式。

    演示:

    import pprint
    
    playerinfo = [("ansonca01",4,1871,1,"RC1"),\
                  ("forceda01",44,1871,1,"WS3"),\
                  ("mathebo01",68,1871,1,"FW1")]
    
    idmatch = [("ansonca01","Anson","Cap","05/06/1871"),\
               ("aaroh101","Aaron","Hank","04/13/1954"),\
               ("aarot101","Aaron","Tommie","04/10/1962")]
    
    result = {}
    for i in playerinfo:
        result[i[0]] =  list(i[:])
    
    print "Debug Rsult1:"
    pprint.pprint(result)
    
    for i in idmatch:
        if i[0] in result:
            result[i[0]].extend(list(i[1:])) 
    
    print "\nDebug Rsult2:"
    pprint.pprint(result)
    
    final_rs = []
    for i,j in result.items():
        final_rs.append(tuple(j))
    
    print "\nFinal result:"
    
    pprint.pprint(final_rs)
    

    输出:

    infogrid@infogrid-vivek:~/workspace/vtestproject$ python task4.py 
    Debug Rsult1:
    {'ansonca01': ['ansonca01', 4, 1871, 1, 'RC1'],
     'forceda01': ['forceda01', 44, 1871, 1, 'WS3'],
     'mathebo01': ['mathebo01', 68, 1871, 1, 'FW1']}
    
    Debug Rsult2:
    {'ansonca01': ['ansonca01', 4, 1871, 1, 'RC1', 'Anson', 'Cap', '05/06/1871'],
     'forceda01': ['forceda01', 44, 1871, 1, 'WS3'],
     'mathebo01': ['mathebo01', 68, 1871, 1, 'FW1']}
    
    Final result:
    [('ansonca01', 4, 1871, 1, 'RC1', 'Anson', 'Cap', '05/06/1871'),
     ('forceda01', 44, 1871, 1, 'WS3'),
     ('mathebo01', 68, 1871, 1, 'FW1')]
    infogrid@infogrid-vivek:~/workspace/vtestproject$ 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-09
      • 1970-01-01
      • 2023-01-26
      • 2016-11-25
      • 2017-03-22
      • 2013-09-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多