-1

I have a list of variables, the number of which can change. Each variable has a lower limit, upper limit and an increment value. For example:

variables = {
   "a": [1, 10, 1],
   "b": [50, 200, 5],
   "c": [50, 300, 10]
}

Where for key "a", 1 is the lower limit, 10 is the upper limit and 1 is the increment amount.

"a" would go from 1 through 10, incrementing by 1
"b" would go from 50 through 200, incrementing by 5
"c" would go from 50 through 300, incrementing by 10
... there can be more or less such keys.

I need to create a list of all possible combinations of a, b and c, without hard coding nested loops, as there are an unknown number of variables/keys, and just cannot wrap my head around it. I'm using Python 3.7

The output would ideally be a table of combinations of each variable, perhaps comma separated values. For example.

a  b  c
x  y  z
x  y  z
x  y  z
x  y  z

However, anything will do, as long as I can collate the output into a format where each combination can be accessed as a set. Such as a list of tuples.

[
  (x, y, z)
  (x, y, z)
]
...

4 Answers4

1

Here, assuming:

variables = {
   "a": [1, 10, 1],
   "b": [50, 200, 5],
   "c": [50, 300, 10]
}

Then you can create an iterator using itertools:

from itertools import product, starmap
cartesian_product = product(*starmap(range, variables.values()))

Or, just to show you what starmap is doing:

cartesian_product = product(*(range(*v) for v in variables.values()))
juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
  • Thank you so much! Just one more question here. Would the order of the keys in the source code definition of the dict be always reflected in the order of the tuple elements? Or do you suggest I use an OrderedDict? – Sid Khullar Feb 14 '20 at 09:51
  • @SidKhullar if you are using python version >= 3.7 then yes, it maintains insertion order. Otherwise, it doesn't. – juanpa.arrivillaga Feb 14 '20 at 09:52
  • Some of my values are floats and this is causing a TypeError. Would you be able to suggest a solution please? – Sid Khullar Feb 14 '20 at 17:15
0

Try:

import numpy as np
lst = [np.arange(v[0], v[1]+1, v[2]) for k,v in variables.items()]
np.array(np.meshgrid(*lst)).T.reshape(-1,len(lst))
luigigi
  • 4,146
  • 1
  • 13
  • 30
  • Thank you. This appears to require a known number of variables. – Sid Khullar Feb 14 '20 at 09:09
  • 1
    While this code might answer the question, can you consider adding some explanation for what the problem was you solved, and how you solved it? This will help future readers to understand your answer better and learn from it. – Uwe Allner Feb 14 '20 at 10:11
0

Try this way:

var=[]
for k in variables.keys():
  var.append(np.arange(variables[k][0],variables[k][1]+1,variables[k][2]))

np.array(np.meshgrid(var[0],var[1],var[2])).T.reshape(-1,3)

for combination I took help from here

Shubham Shaswat
  • 1,250
  • 9
  • 14
0

You can use itertools:

import numpy as np
import itertools


a = np.arange(1, 10, 1)
b = np.arange(50, 200, 5)
c = np.arange(50,300,10)

results = itertools.product(a, b, c)
for item in results:
    print(item)

Output:

(1, 50, 50)
(1, 50, 60)
...
...
(9, 195, 270)
(9, 195, 280)
(9, 195, 290)
Błotosmętek
  • 12,717
  • 19
  • 29
Zaraki Kenpachi
  • 5,510
  • 2
  • 15
  • 38