Python3 - 3个变量= x的所有可能组合

时间:2018-02-06 00:38:05

标签: python python-3.x itertools

我正在尝试找到所有可能的组合,其中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。

3 个答案:

答案 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-yz。对三个列表进行预先处理,以便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.productitertools.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}