(我知道问题的标题可能会产生误导,但我找不到任何其他方式来制定它 - 随意编辑它)
我有两个相同长度的列表:
a = [1,2,3]
b = [4,5,6]
我想用第二个列表获取第一个列表的所有可能替换。
output[0] = [1,2,3] # no replacements
output[1] = [4,2,3] # first item was replaced
output[2] = [1,5,3] # second item was replaced
output[3] = [1,2,6] # third item was replaced
output[4] = [4,5,3] # first and second items were replaced
output[5] = [4,2,6] # first and third items were replaced
output[6] = [1,5,6] # second and third items were replaced
output[7] = [4,5,6] # all items were replaced
请注意,以下问题无法解答此问题:
涉及先前链接的答案的可能解决方案是创建多个列表,然后对它们使用 itertools.product 方法。例如,我可以创建3个2个元素的列表,而不是2个3个元素的列表。但是,这会使代码过于复杂,如果可以,我宁愿避免这样做。
有一种简单快捷的方法吗?
答案 0 :(得分:3)
每个项目可以单独更换或单独保留。这可以通过1或0来建模。如果您认为每个项都是一个单独的位,那么迭代所有可能性可以映射到迭代 n 位的所有组合
换句话说,迭代从0到2 n -1并查看位模式。
n = len(a)
for i in range(2**n):
yield [a[j] if i & (1 << j) != 0 else b[j] for j in range(n)]
将其断开,i & (1 << j) != 0
检查 i 的 j 是否已设置。如果是,请使用a[j]
,否则使用b[j]
。
结果:
[1, 2, 3]
[4, 2, 3]
[1, 5, 3]
[4, 5, 3]
[1, 2, 6]
[4, 2, 6]
[1, 5, 6]
[4, 5, 6]
答案 1 :(得分:3)
创建3个两个元素的列表根本不会使代码过于复杂。 zip
can "flip the axes" of multiple lists非常简单(将Y元素的X序列转换为X元素的Y序列),使其易于使用itertools.product
:
import itertools
a = [1,2,3]
b = [4,5,6]
# Unpacking result of zip(a, b) means you automatically pass
# (1, 4), (2, 5), (3, 6)
# as the arguments to itertools.product
output = list(itertools.product(*zip(a, b)))
print(*output, sep="\n")
哪个输出:
(1, 2, 3)
(1, 2, 6)
(1, 5, 3)
(1, 5, 6)
(4, 2, 3)
(4, 2, 6)
(4, 5, 3)
(4, 5, 6)
与您的示例输出不同的顺序,但它是同一组可能的替换。
答案 2 :(得分:0)
好的,这与其他答案类似,但从中取一点。您可以将问题建模为查找给定长度序列的所有可能位,并仅在有1时替换,否则不替换。
with open(USER_DATA,'r') as file:
f = encodeutils.safe_encode(file.read().encode('utf-8'))
init_script = base64.b64encode(f).decode('utf-8')
所有位组合均为:
from itertools import product
a = [1,2,3]
b = [4,5,6]
## All binary combinations of length of a (or b)
combinations = product([0,1], repeat=len(a))
for combination in combinations:
y = []
for l, i in zip(zip(a,b),combination):
y.append(l[i])
print y
结果是:
(0, 0, 0)
(0, 0, 1)
(0, 1, 0)
(0, 1, 1)
(1, 0, 0)
(1, 0, 1)
(1, 1, 0)
(1, 1, 1)