Python 在列表之间获得独特的产品,并维护输入顺序

Python 在列表之间获得独特的产品,并维护输入顺序,python,unique,generator,cartesian-product,Python,Unique,Generator,Cartesian Product,关于列表的独特(笛卡尔)积有很多问题,但我正在寻找一些我在其他任何问题中都没有发现的奇特的东西 我的输入将始终由两个列表组成。当列表相同时,我希望获得所有组合,但当它们不同时,我需要唯一的产品(即,顺序无关紧要)。但是,另外,我还需要保留顺序,因为输入的顺序非常重要。事实上,我需要的是,第一个列表中的项应该始终是产品元组的第一项 我有下面的工作代码,它实现了我想要的功能,除了我没有找到一个好的、有效的方法来保持上面所描述的物品的有序 import itertools xs = ['w'] ys

关于列表的独特(笛卡尔)积有很多问题,但我正在寻找一些我在其他任何问题中都没有发现的奇特的东西

我的输入将始终由两个列表组成。当列表相同时,我希望获得所有组合,但当它们不同时,我需要唯一的产品(即,顺序无关紧要)。但是,另外,我还需要保留顺序,因为输入的顺序非常重要。事实上,我需要的是,第一个列表中的项应该始终是产品元组的第一项

我有下面的工作代码,它实现了我想要的功能,除了我没有找到一个好的、有效的方法来保持上面所描述的物品的有序

import itertools

xs = ['w']
ys = ['a', 'b', 'c']

def get_up(x_in, y_in):
    if x_in == y_in:
        return itertools.combinations(x_in, 2)
    else:
        ups = []
        for x in x_in:
            for y in y_in:
              if x == y:
                  continue
              # sort so that cases such as (a,b) (b,a) get filtered by set later on
              ups.append(sorted((x, y)))
        ups = set(tuple(up) for up in ups)
        return ups

print(list(get_up(xs, ys)))
# [('c', 'w'), ('b', 'w'), ('a', 'w')]
如您所见,结果是按字母顺序排列的唯一元组列表。我使用了排序,这样我就可以使用集合来过滤重复的条目。但是因为第一个列表(
xs
)包含
w
,所以我希望元组将该
w
作为第一项

[('w', 'c'), ('w', 'b'), ('w', 'a')]
如果两个列表之间存在重叠,则两个列表中出现的项目顺序无关紧要,因此对于
xs=['w','a','b']
ys=['a','b','c']
而言,
a
的顺序无关紧要

[('w', 'c'), ('w', 'b'), ('w', 'a'), ('a', 'b'), ('a', 'c'), ('b', 'c')]
                                         ^


最好是以生成器结束(作为
组合
返回)。我也只对Python>=3.6感兴趣。

我会回答我自己的问题,尽管我打赌使用itertools或其他工具会有更好的解决方案

xs = ['c', 'b']
ys = ['a', 'b', 'c']


def get_unique_combinations(x_in, y_in):
    """ get unique combinations that maintain order, i.e. x is before y """
    yielded = set()
    for x in x_in:
        for y in y_in:
            if x == y or (x, y) in yielded or (y, x) in yielded:
                continue

            yield x, y
            yielded.add((x, y))

    return None

print(list(get_unique_combinations(xs, ys)))

以保留顺序的方式收集元组(当列表相同时),然后通过移除其逆项也在列表中的元组进行过滤

if x_in == y_in:
        return itertools.combinations(x_in, 2) 
    else:
        seen = set()
        for a,b in itertools.product(x_in, y_in):
            if a == b or (b, a) in seen:
                continue
            else:
                yield (a,b)
                seen.add((a,b))
这将为您提供
(x,y)
顺序的元组;当
(a,b)
(b,a)
同时出现时,您只会得到最先看到的顺序

if x_in == y_in:
        return itertools.combinations(x_in, 2) 
    else:
        seen = set()
        for a,b in itertools.product(x_in, y_in):
            if a == b or (b, a) in seen:
                continue
            else:
                yield (a,b)
                seen.add((a,b))