C. *_*ppy 6 python optimization python-itertools
我想从两个列表中有效地生成元素对,这些元素等于它们的笛卡尔积,并省略了一些元素。每个列表中的元素都是唯一的。
下面的代码完全满足了需要,但我希望通过替换循环来优化它。
详细内容请参见代码中的注释。
任何意见,将不胜感激。
from itertools import product
from pprint import pprint as pp
def pairs(list1, list2):
    """ Return all combinations (x,y) from list1 and list2 except:
          1. Omit combinations (x,y) where x==y """
    tuples = filter(lambda t: t[0] != t[1], product(list1,list2))
    """   2. Include only one of the combinations (x,y) and (y,x) """
    result = []
    for t in tuples:
        if not (t[1], t[0]) in result:
            result.append(t)
    return result
list1 = ['A', 'B', 'C']
list2 = ['A', 'D', 'E']
pp(pairs(list1, list1))  #  Test a list with itself
pp(pairs(list1, list2))  #  Test two lists with some common elements
输出
[('A', 'B'), ('A', 'C'), ('B', 'C')]
[('A', 'D'),
 ('A', 'E'),
 ('B', 'A'),
 ('B', 'D'),
 ('B', 'E'),
 ('C', 'A'),
 ('C', 'D'),
 ('C', 'E')]
比您的答案基准中最快的速度快大约 5-6 倍。我构建了出现在两个列表或仅一个列表中的一组值,并将它们适当地组合起来,而无需进一步过滤。
from itertools import product, combinations
def pairs(list1, list2):
    a = {*list1}
    b = {*list2}
    ab = a & b
    return [
        *product(a, b-a),
        *product(a-b, ab),
        *combinations(ab, 2)
    ]
您还可以将其设为迭代器(因为与以前的解决方案不同,我不需要存储已生成的对来过滤更多的对):
from itertools import product, combinations, chain
def pairs(list1, list2):
    a = {*list1}
    b = {*list2}
    ab = a & b
    return chain(
        product(a, b-a),
        product(a-b, ab),
        combinations(ab, 2)
    )