0

Which would be the most elegant and Pythonic way to permute elements of 5 or 6 lists?

I have a bunch of list like following, where each element will trigger an AJAX call. And when elements from list 3 will be iterated, they might pull out another list which I need to permute as well and I need to get all permutations possible.

List comprehensions are out of discussion because I need to make some operations between each call.

I know about itertools.permutations but I'm looking for something that will give me more control at each step.

list1 =['e1', 'e2', 'e3']
list2 = ['e1', 'e2', ... , 'e13']
list3 = [up to 15 elements]
variable_list = ['e1', 'e2']
list4 = ['e1', 'e2']
list5 = ['e1', 'e2', ... , 'e16']

Here it's the list I'm trying to deal:

values = [[{'0': '25'},
      {'0': '50'},
      {'0': '75'},
      {'0': '100'},
      {'0': '250'},
      {'0': '500'},
      {'0': '750'},
      {'0': '1000'},
      {'0': '2500'},],
     [{'1': 'abc|xyz'}],
     [{'2': 'Color|purple'}, {'2': 'Color|black'}],
     [{'3': 'yes|no'},
      {'3': 'no|yes'}],
     [{'4': 'Round|no'}, {'4': 'Round|yes'}],
     [{'5': 'time|4-5'}],
     [{'Base': 'gl'}],
     [{'Type': '123'}]]

The number of values elements may change, not all the time will have this length - 8 elements, so I need to handle that as well.

I need to return a list with all combinations possible: Here's an example of an element from the list which I need:

[{'0': '25'}, {'1': 'abc|xyz'}, {'2': 'Color|purple'}, {'3': 'yes|no'}, {'4': 'Round|no'}, {'5': 'time|4-5'}, {'Base': 'gl'}, {'Type': '123'}]

The length of each element from resulted list has to be equal with the length on input list (value in my case).

I tried itertools.permutation but is giving me more results than I need. Also, I tried @markcial suggestion but it doesn't work if I don't know the length of the input list before hand.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
jabez
  • 896
  • 1
  • 9
  • 22
  • I'm not sure I understand what you mean when you say you need control at each step. Are you modifying the lists as you are generating the permutations? – Andrew Clark Jan 30 '14 at 20:53
  • 1
    How do you mean more control at each step? permutations isn't computed all at once, but rather is a generator that yields them to you one at a time. you can break iterating part-way through and it won't keep computing the remaining permutations – mhlester Jan 30 '14 at 20:53
  • No, I'm not modifying them, but I need classic for loop because at each iteration I'll need to extract some data from AJAX calls. It's very important to do this top to bottom and not random. – jabez Jan 30 '14 at 20:55
  • itertools.permutations isn't random – mhlester Jan 30 '14 at 20:56
  • No, I do not need a get a list of full results, I just need to iterate over each permute. – jabez Jan 30 '14 at 20:57
  • 1
    It sounds like itertools.permutations should work just fine. – Andrew Clark Jan 30 '14 at 20:58
  • you can permute and call a function in each list comprehension step – markcial Jan 30 '14 at 20:58
  • How I'd manage the variable list? I need to iterate through it only if exists, and will not exist all the time. – jabez Jan 30 '14 at 20:59
  • Have you written any code yet? It might be more clear what you're trying to do if you post what you've done so far. Then we can suggest more concise approaches. – Kevin Jan 30 '14 at 21:01
  • No code yet, I don't know what approach to use :( – jabez Jan 30 '14 at 21:04
  • Is it that you want to iterate over all the possible permutations in parallel? Meaning access first element of all of them, then second element of all of them? And you want to make sure that the sequence of all permutations is always the same? As @mhlester pointed out, the itertools.permutations output is completely deterministic, you will always get them in the same order. – Diana Jan 30 '14 at 21:06
  • possible duplicate of [How to generate all permutations of a list in Python](http://stackoverflow.com/questions/104420/how-to-generate-all-permutations-of-a-list-in-python) – maxywb Jan 30 '14 at 21:07
  • It isn't clear what you *really* want to do. Because of that, it's hard to give a proper suggestion. – Karoly Horvath Jan 30 '14 at 21:15

2 Answers2

1

You talk about permutations and combinations, but it seems to me you actually want the Cartesian product, which is generated by itertools.product. For example:

>>> from itertools import product
>>> values = [[{'0': '25'}, {'0': '50'}, {'0': '75'}, {'0': '100'}, {'0': '250'}, {'0': '500'}, {'0': '750'}, {'0': '1000'}, {'0': '2500'}], [{'1': 'abc|xyz'}], [{'2': 'Color|purple'}, {'2': 'Color|black'}], [{'3': 'yes|no'}, {'3': 'no|yes'}], [{'4': 'Round|no'}, {'4': 'Round|yes'}], [{'5': 'time|4-5'}], [{'Base': 'gl'}], [{'Type': '123'}]]
>>> every_choice = list(product(*values))
>>> len(every_choice)
72

Where each element of every_choice is a tuple with one element selected from each list:

>>> every_choice[0]
({'0': '25'}, {'1': 'abc|xyz'}, {'2': 'Color|purple'}, {'3': 'yes|no'}, {'4': 'Round|no'}, {'5': 'time|4-5'}, {'Base': 'gl'}, {'Type': '123'})
>>> every_choice[30]
({'0': '100'}, {'1': 'abc|xyz'}, {'2': 'Color|black'}, {'3': 'no|yes'}, {'4': 'Round|no'}, {'5': 'time|4-5'}, {'Base': 'gl'}, {'Type': '123'})
>>> every_choice[-1]
({'0': '2500'}, {'1': 'abc|xyz'}, {'2': 'Color|black'}, {'3': 'no|yes'}, {'4': 'Round|yes'}, {'5': 'time|4-5'}, {'Base': 'gl'}, {'Type': '123'})
DSM
  • 342,061
  • 65
  • 592
  • 494
0

list comprehension is able to call functions too. You can create a function for the list comprehension step like this

def do(*args):
    print args
    return args

and then with list comprehension call the function with the current step:

list1 =['e1', 'e2', 'e3']
list2 = ['e1', 'e2', 'e13']
[do(a,b) for a in list1 for b in list2]

subsequent loops can be added with more complex routines, but the main idea is that you can control list comprehension loops

markcial
  • 9,041
  • 4
  • 31
  • 41