5

I am looking for a method to dive into a list and directly access its elements. For example, the following is the normal way of getting the Cartesian product of for sets.

>>> list(itertools.product((0,1), (0,1),(0,1),(0,1)))
[(0, 0, 0, 0), (0, 0, 0, 1), (0, 0, 1, 0), (0, 0, 1, 1), (0, 1, 0, 0), (0, 1, 0, 1), (0, 1, 1, 0), (0, 1, 1, 1), (1, 0, 0, 0), (1, 0, 0, 1), (1, 0, 1, 0), (1, 0, 1, 1), (1, 1, 0, 0), (1, 1, 0, 1), (1, 1, 1, 0), (1, 1, 1, 1)]

But in this case the four sets are identical, and it soon gets boring and tiresome to have to type it over and over again, which makes one think of doing this instead:

>>> list(itertools.product([(0,1)]*4)

But of course it won't work, since the itertools.product function will see it as one set instead of four sets. So, the question is, is there a way to do this:

>>> list(itertools.product(delist([(0,1)]*4))
qed
  • 22,298
  • 21
  • 125
  • 196
  • Perhaps you should consider creating some class or perhaps a pair of classes to encapsulate the details of this data and expose the operations you want to perform on instances as object methods. – Jim Dennis Jan 08 '12 at 07:19

2 Answers2

10
itertools.product((0,1), repeat=4)

The product function accepts an optional repeat argument. The above is equivalent to itertools.product((0, 1), (0, 1), (0, 1), (0, 1)).


In general, if you have a list

lst = [1, 2, 4, 6, 8, ...]

and you'd like to call a function as

f(1, 2, 4, 6, 8, ...)

you could use the * (unpack) operator to expand the list into an argument list:

f(*lst)
Community
  • 1
  • 1
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • so he just needed to add the *, i.e. list(itertools.product(*[(0,1)]*4)) although using repeat is better – Rusty Rob Jan 08 '12 at 07:10
  • This is embarrassing, I should have read the documentation first. That being said, there is a small mistake in your answer, should be `itertools.product((0,1), repeat=4)`, still a helpful answer neverthless. Thank you. – qed Jan 08 '12 at 07:17
5

If you aren't using itertools.product, you could also use the * operator. The * operator does whatever I think you mean by "delist." It transforms the contents of a list or other iterable object into positional arguments for a function. In general:

args = ['arg1', 'arg2', 'arg3', 'arg4']

# The following two calls are exactly equivalent
func('arg1', 'arg2', 'arg3', 'arg4')
func(*args)

In this specific example, the code would look like this:

itertools.product(*[(0,1)]*4)

However, the previous answer (by KennyTM) is probably cleaner in the specific case of itertools.product:

itertools.product((0, 1), repeat=4)
HardlyKnowEm
  • 3,196
  • 20
  • 30