我正在尝试找到所有可能的组合,其中3个变量可以=某个数字。
x = (10,11,12,13,14,15)
y = (10,11,12,13,14,15)
z = (10,11,12,13,14,15)
answer = 45
我如何使用itertools查找
的每个组合x + y + z = 45
在这种情况下,我希望python打印(15,15,15) 但是,如果答案是=到一个不同的数字,如30,它将打印x,y,z的每个组合,当添加时将= 45。
答案 0 :(得分:6)
您可以使用itertools.product
:
import itertools
x = (10,11,12,13,14,15)
y = (10,11,12,13,14,15)
z = (10,11,12,13,14,15)
answer = 45
final_results = [i for i in itertools.product(x, y, z) if sum(i) == answer]
输出:
[(15, 15, 15)]
答案 1 :(得分:6)
您可以使用列表推导而不是itertools
x = (10,11,12,13,14,15)
y = (10,11,12,13,14,15)
z = (10,11,12,13,14,15)
answer = 35
res = [(i, j, answer - i - j) for i in x for j in y if (answer - i - j) in set(z)]
print(res)
正如@RoryDaulton在评论中指出的那样,这种方法的优势在于它是一种O(n ^ 2)方法,结合O(1)查询时间进行测试,如果answer-x-y
在z
。对三个列表进行预先处理,以便z
是最长的列表,应该减少此操作所需的时间。
我也测量了执行时间。测试清楚地表明保罗的代码是最快的:
n = 100
x, y, z = map(list, map(range, 3*(2 * n,)))
any(map(random.shuffle, (x, y, z)))
x, y, z = x[:n], y[:n], z[:n]
answer = 4 * n
def f1(): #team Ajax
final_results = [i for i in itertools.product(x, y, z) if sum(i) == answer]
return final_results
def f2(): #team Pie
res = [(i, j, answer - i - j) for i in x for j in y if (answer - i - j) in set(z)]
return res
def f3(): #team Paul
xy = sorted(itertools.product(x, y), key=sum)
xy = {k: list(v) for k, v in itertools.groupby(xy, sum)}
xyz = [(a, b, c) for c in z for a, b in xy.get(answer-c, ())]
return xyz
repeats = 10
print("f1", timeit.repeat("f1()", "from __main__ import f1", number = repeats))
>>>f1 [1.741] #team Ajax
print("f2", timeit.repeat("f2()", "from __main__ import f2", number = repeats))
>>>f2 [0.221] #team Pie
print("f3", timeit.repeat("f3()", "from __main__ import f3", number = repeats))
>>>f3 [0.051] #team Paul
(它只显示每个程序的最快值)
答案 2 :(得分:4)
这是itertools.product
,itertools.groupby
方法:
>>> import random
>>> import itertools
>>>
# create random lists
>>> x, y, z = map(list, map(range, 3*(20,)))
>>> any(map(random.shuffle, (x, y, z)))
False
>>> x, y, z = x[:10], y[:10], z[:10]
>>>
# choose a sum
>>> sum_ = 40
>>>
# compute and sort all sums of the first two
>>> xy = sorted(itertools.product(x, y), key=sum)
# and group by these sums
>>> xy = {k: list(v) for k, v in itertools.groupby(xy, sum)}
# use this to look up the matching x, y if any for each z
>>> xyz = [(a, b, c) for c in z for a, b in xy.get(sum_-c, ())]
>>> xyz
[(18, 4, 18), (16, 6, 18), (6, 16, 18), (4, 18, 18), (5, 18, 17), (7, 16, 17), (18, 5, 17), (16, 7, 17), (16, 16, 8), (7, 18, 15), (18, 7, 15), (16, 9, 15), (5, 16, 19), (11, 10, 19), (18, 3, 19), (16, 5, 19), (18, 16, 6), (16, 18, 6), (11, 18, 11), (11, 16, 13), (18, 9, 13)]
>>>
# validate
>>> set(map(sum, xyz))
{40}