【问题标题】:Pair elements from two different lists对来自两个不同列表的元素
【发布时间】:2018-04-07 02:02:14
【问题描述】:

我有两个列表:

listA = ['a1', 'a2', 'a3', 'a4']
listB = ['b2', 'b4']

我想以 任何字符串相同的数字的格式对项目进行配对,如下所示:

listC = [('a1', None),('a2', 'b2'),('a3', None),('a4', 'b4')]

我尝试过itertools.zip_longest,但我无法得到我需要的东西:

>>>list(itertools.zip_longest(listA, listB)
[('a1', 'b2'), ('a2', 'b4'), ('a3', None), ('a4', None)]

对如何获得listC有任何建议吗?

【问题讨论】:

    标签: python list


    【解决方案1】:

    您可以将iternext 一起使用:

    listA = ['a1', 'a2', 'a3', 'a4']
    listB = ['b2', 'b4']
    l = iter(listB)
    listC = [(a, next(l) if i%2 != 0 else None) for i, a in enumerate(listA)] 
    

    输出:

    [('a1', None), ('a2', 'b2'), ('a3', None), ('a4', 'b4')]
    

    编辑:按尾随数字配对:

    import re
    listA = ['a1', 'a2', 'a3', 'a4']
    listB = ['b2', 'b4']
    d = {re.findall('\d+$', b)[0]:b for b in listB}
    listC = [(i, d.get(re.findall('\d+$', i)[0])) for i in listA]
    

    输出:

    [('a1', None), ('a2', 'b2'), ('a3', None), ('a4', 'b4')]
    

    【讨论】:

    • 这仅在 listB 始终是 listA 的子集时才有效。也许这就是 OP 想要的,但问题并不清楚。
    • 这是对 OP 想要什么的大胆猜测,但他后来发表了一条评论,明确表示你没有正确回答它所需要的超人心灵感应……
    • @abarnert 你能澄清一下吗?
    • @Ajax1234 阅读他对这个问题的评论:他想将具有相同数字的字符串配对,而不是跳过较短列表中的所有其他元素。
    【解决方案2】:

    您可以为此使用带有三元语句的列表推导:

    listA = ['a1', 'a2', 'a3', 'a4']
    listB = ['b2', 'b4']
    
    listB_set = set(listB)
    listC = [(i, 'b'+i[1:] if 'b'+i[1:] in listB_set else None) for i in listA]
    
    # [('a1', None), ('a2', 'b2'), ('a3', None), ('a4', 'b4')]
    

    但是,为了清晰和性能,我会考虑将数字和字符串数据分开。

    【讨论】:

      【解决方案3】:

      你可以试试dict方法:

      listA = ['a1', 'a2', 'a3', 'a4']
      listB = ['b2', 'b4']
      
      final_list={}
      import itertools
      
      for i in itertools.product(listA,listB):
          data,data1=list(i[0]),list(i[1])
          if data[1]==data1[1]:
              final_list[i[0]]=i
          else:
              if i[0] not in final_list:
                  final_list[i[0]]=(i[0],None)
      
      print(final_list.values())
      

      输出:

      [('a2', 'b2'), ('a3', None), ('a4', 'b4'), ('a1', None)]
      

      【讨论】:

        【解决方案4】:

        给定

        import itertools as it
        
        
        list_a = ["a1", "a2", "a3", "a4"]
        list_b = ["b2", "b4"]
        

        代码

        pred = lambda x: x[1:]
        res = [tuple(g) for k, g in it.groupby(sorted(list_a + list_b, key=pred), pred)]
        res
        # [('a1',), ('a2', 'b2'), ('a3',), ('a4', 'b4')]
        
        list(zip(*it.zip_longest(*res)))
        # [('a1', None), ('a2', 'b2'), ('a3', None), ('a4', 'b4')]
        

        详情

        一个扁平的排序列表按每个字符串的数字分组,并根据谓词产生分组results。请注意,如果字符串以 单个 字母开头,则谓词应适用于任何数字,"a1""b23""c132" 等。如果您愿意,也可以考虑使用尾随在@Ajax1234's answer 中看到的数字正则表达式。

        如您所见,itertools.zip_longest 默认将None 填充为更短的子组。

        另见

        • this post 了解有关填充可迭代对象的更多想法
        • this post 如何使用 itertool.groupby
        • this post 关于自然排序以获得更强大的谓词

        【讨论】:

        • 那个len(max(res))是最后一个元组的长度,不是最长元组的长度;您需要在其中添加一个key=len
        • 另外,这里不需要lambda;我认为itemgetter(1) 对新手来说可能会更清晰一些(或者至少给他们一些他们可以查找的东西),并且速度会快一点。
        • 谢谢@abarnert。 len 关键字微妙而富有洞察力。我仍在努力解析数字,所以我想lambda 现在可能更灵活。
        • 是的,lambda 在灵活性方面绝对有优势。如果 OP 回来说“它不适用于 c27”,您只需将 x[1] 更改为 x[1:]
        猜你喜欢
        • 2021-12-07
        • 1970-01-01
        • 1970-01-01
        • 2019-04-26
        • 1970-01-01
        • 2022-01-22
        • 1970-01-01
        • 1970-01-01
        • 2019-03-08
        相关资源
        最近更新 更多