获取列表之间的唯一产品并维护输入顺序
Get unique products between lists and maintain order of input
有很多关于列表的唯一(笛卡尔)乘积的问题,但我正在寻找我在其他任何问题中都没有找到的奇特的东西。
我的输入总是包含两个列表。当列表相同时,我想获得所有组合,但当它们不同时,我需要唯一的产品(即顺序无关紧要)。 但是,此外我还需要保留顺序,因为 input 列表的顺序很重要。事实上,我需要的是第一个列表中的项目应该始终是产品元组的第一个项目。
我有以下工作代码,除了我没有设法找到一种好的、有效的方法来保持项目按上述顺序排列外,它可以满足我的要求。
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')]
^
或
[('w', 'c'), ('w', 'b'), ('w', 'a'), ('a', 'c'), ('b', 'a'), ('b', 'c')]
^
最好我最终得到一个生成器(如 combinations
returns)。我也只对 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)
都出现时,您只会得到最先看到的顺序。
有很多关于列表的唯一(笛卡尔)乘积的问题,但我正在寻找我在其他任何问题中都没有找到的奇特的东西。
我的输入总是包含两个列表。当列表相同时,我想获得所有组合,但当它们不同时,我需要唯一的产品(即顺序无关紧要)。 但是,此外我还需要保留顺序,因为 input 列表的顺序很重要。事实上,我需要的是第一个列表中的项目应该始终是产品元组的第一个项目。
我有以下工作代码,除了我没有设法找到一种好的、有效的方法来保持项目按上述顺序排列外,它可以满足我的要求。
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')]
^
或
[('w', 'c'), ('w', 'b'), ('w', 'a'), ('a', 'c'), ('b', 'a'), ('b', 'c')]
^
最好我最终得到一个生成器(如 combinations
returns)。我也只对 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)
都出现时,您只会得到最先看到的顺序。