简体   繁体   English

如何获得两个列表中整数和运算的所有组合?

[英]How to get all combinations of integers and operations across two lists?

I have two lists: 我有两个清单:

ints = [10, 20, 30, 40, 50]

and

opers = ['+', '-', '*', '/']

I would like to obtain a list which has all possible combinations of these two lists such as: 我想获得一个包含这两个列表的所有可能组合的列表,例如:

10+20*40-30/50 = 810

50-40+30*20/10 = 70

etc. 等等

The list should then be [810, 70, ...] 列表应为[810, 70, ...]

I believe there should be 2880 total elements in this list. 我相信此列表中应该总共有2880个元素。 If int[0]==int[1] , they'll count as separate for this purpose. 如果int[0]==int[1] ,则为此将它们视为单独的。

I think I'll have to use eval() two actually get the elements in the list. 我想我将不得不使用eval()两个实际上获取列表中的元素。 I just can't figure out how to permute the two lists in this way. 我只是不知道如何以这种方式排列两个列表。 Any help will be appreciated. 任何帮助将不胜感激。

Thank you 谢谢

The key is to use the itertools.permutations function. 关键是使用itertools.permutations函数。 This is the naive way: 这是幼稚的方式:

import itertools

ints = [10, 20, 30, 40, 50]
opers = ['+', '-', '*', '/']

for i in itertools.permutations(ints):
    for o in itertools.permutations(opers):
        s = f'{i[0]}{o[0]}{i[1]}{o[1]}{i[2]}{o[2]}{i[3]}{o[3]}{i[4]}'
        print(f'{s} = {eval(s)}')

output looks something like this (obviously you could place in a dictionary or whatever): 输出看起来像这样(很明显,您可以将其放在字典中或其他内容中):

...
50-10/30+40*20 = 849.6666666666666
50-10/30*40+20 = 56.66666666666667
50*10+30-40/20 = 528.0
50*10+30/40-20 = 480.75
50*10-30+40/20 = 472.0
50*10-30/40+20 = 519.25
50*10/30+40-20 = 36.66666666666667
50*10/30-40+20 = -3.333333333333332
50/10+30-40*20 = -765.0
50/10+30*40-20 = 1185.0
50/10-30+40*20 = 775.0
50/10-30*40+20 = -1175.0
50/10*30+40-20 = 170.0
50/10*30-40+20 = 130.0
50+10-40*20/30 = 33.33333333333333
...

Create all permutations, remove those that do not fit ( number number ops ... etc) and calc: 创建所有排列,删除不适合的排列(数字运算...等)并计算:

from itertools import permutations

ints = ['10', '20', '30', '40', '50']
opers = [ '+', '-', '*', '/']


perm = permutations(ints+opers)

# sets for faster lookup    
i = set(ints)
ops = set(opers)

fil = (p for p in perm 
       if all(p[k] in i if k%2==0 else p[k] in ops 
              for k in range(len(p))))

calcMe = [''.join(f) for f in fil]

calcMe = [''.join(f) for f in fil]
for cal in calcMe:
    print(f"{cal}={eval(cal)}")
print(len(calcMe))

Output: 输出:

10+20-30*40/50=6.0
10+20-30*50/40=-7.5
10+20-30/40*50=-7.5
10+20-30/50*40=6.0
10+20-40*30/50=6.0
10+20-40*50/30=-36.66666666666667
10+20-40/30*50=-36.66666666666666
10+20-40/50*30=6.0

There are more permutations provided then needed and 'eval' in and of itself is considered "dangerous" if applied without thought. 如果需要,还会提供更多需要的排列,如果不加思索地将其“评估”本身视为“危险”。 In this case it should be ok, though as I have full control over the inputs. 在这种情况下应该可以,尽管我可以完全控制输入。

from itertools import permutations, zip_longest, chain

def all_combinations(ints, ops):
    for i in permutations(ints):
        for o in permutations(ops):
            yield "".join(filter(bool(chain.from_iterable(zip_longest(i, o)))))

The somewhat cryptic last line does the following: 最后一行有些神秘,它执行以下操作:

For a given permutation of integers and operators, zip them (with missing values being None ). 对于整数和运算符的给定排列,请压缩它们(缺失值为None )。 Chain those zipped pairs together, to form a sort of "combing" operation. 将那些拉链对链接在一起,以形成一种“精梳”操作。 The filter(bool, ...) call removes the None , depending on your taste there may be other ways you'd prefer. filter(bool, ...)调用将删除None ,这取决于您的喜好,您可能会喜欢其他方法。 Finally, str.join turns the integer-operator sequence into a string. 最后, str.join将整数运算符序列转换为字符串。

You can create the list like this, using some itertools : 您可以使用一些itertools这样创建列表:

from itertools import permutations, chain, zip_longest

ints = [10, 20, 30, 40, 50]
opers = ['+', '-', '*', '/']

output = []
for int_perm in permutations(ints):
    for op_perm in permutations(opers):
        calculation = ''.join(map(str, chain.from_iterable(zip_longest(int_perm, op_perm, fillvalue=''))))
        output.append(eval(calculation))

print(len(output))
# 2880
print(output)
# [6.0, -7.5, 609.2, -25.0, -1989.3333333333333, ...]

A bit of explanation: for two given permutations of ints and opers : 有点解释:对于intsopers两个给定排列:

(10, 30, 50, 20, 40)
('-', '*', '/', '+')

zip_longest will give us: (note that, as the opers list is shorter, the missing value will be filled by the fillvalue '' ) zip_longest会给我们:(注意,由于opers列表较短,缺少的值将由fillvalue填写''

print(list((zip_longest(int_perm, op_perm, fillvalue=''))))
# [(10, '-'), (30, '*'), (50, '/'), (20, '+'), (40, '')]

and chaining the tuples in this list will give us: 并将此列表中的元组链接将为我们提供:

print(list(chain.from_iterable(zip_longest(int_perm, op_perm, fillvalue=''))))
# [10, '-', 30, '*', 50, '/', 20, '+', 40, '']

We just have to map all items to strings and join them to get: 我们只需要将所有项目映射到字符串并将其联接即可:

# '10-30*50/20+40'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM