2

I'm trying to think of an efficient way of solving the following problem:

Given any two arrays 'a' and 'b' I'd like to create all lists of combinations, each combination should contain tuples of one element from 'a' and one element from 'b'

for example:

a = ['p', 'q'], b = [True, False]

the output should be the following:

[{'p': False, 'q': False}, {'p': False, 'q': True}, {'p': True, 'q': 
False}, {'p': True, 'q': True}]
crommy
  • 433
  • 1
  • 4
  • 12
  • can you append in your post the two arrays 'a' and 'b' ? – Alexall Nov 04 '19 at 08:49
  • I can probably append them, there are no real restrictions, I'm just looking for efficiency – crommy Nov 04 '19 at 08:50
  • You are looking for an implementation or using a module? – sheldonzy Nov 04 '19 at 08:55
  • anything goes really, as long as it works and is efficient.. I've got a working implementation but It's like... O(n^3).. I think it should be doable in O(n^2) – crommy Nov 04 '19 at 08:58
  • 1
    You're looking for the [itertools library](https://docs.python.org/3.7/library/itertools.html#itertools.product), I don't think you'll find anything more efficient in python – olinox14 Nov 04 '19 at 09:04
  • 1
    I've been trying to maybe use the product function from that library. but I can't figure out a way to make what I want without having to iterate over the product and removing the repeated values – crommy Nov 04 '19 at 09:05
  • Does this answer your question? [Making all possible combinations of a list](https://stackoverflow.com/questions/8371887/making-all-possible-combinations-of-a-list) – Itamar Mushkin Nov 04 '19 at 09:05
  • @ItamarMushkin he want dict not array – azro Nov 04 '19 at 09:07
  • What you'r showing is no a tuple, but an array of dict – azro Nov 04 '19 at 09:10
  • 1
    @ItamarMushkin sadly no, this would leave me with the same problem as before. I'd have to weed out the bad combinations that I don't need. – crommy Nov 04 '19 at 09:11

4 Answers4

4

Hey you can use itertools.product with repeat=2

Here is a working example which builds a list of dictionaries

[{k1:v1, k2:v2} for k1,v1,k2,v2 in itertools.product(a,b,repeat=2) if k1 != k2]
megges
  • 570
  • 1
  • 3
  • 11
  • I will add though that this solution takes the length being 2 in to account What I gave was an example. a can be of any length, b in my case can be of just length 2 but I'd like to assume a general case – crommy Nov 04 '19 at 09:28
3
from itertools import product

dicts = [{k:v for k,v in zip(keys, tup)} for tup in list(product(values, repeat=len(keys)))]
fixmycode
  • 8,220
  • 2
  • 28
  • 43
1
a = ['p', 'q']

b = [True, False]
import itertools
result = [{values[0]: values[1]} for values in list(itertools.product(a,b))]

print(result)

is that what you need?

mgruber
  • 751
  • 1
  • 9
  • 26
  • It's a decent start but no, after doing this you'd have to create every possible combination of he dictionaries this function creates – crommy Nov 04 '19 at 09:30
0
from itertools import product
lst = [dict(zip(a,pair)) for pair in product(b,b)]

Output:

[{'p': True, 'q': True},
 {'p': True, 'q': False},
 {'p': False, 'q': True},
 {'p': False, 'q': False}]

EDIT:

Since you say a can be of any length, in that case you don't really need b.

from itertools import permutations
import numpy as np

a = ['p','q','r','s','t']
list1 = list(permuations(a))
set1 = {tuple(np.array(a) == np.array(i)) for i in list1}
final_list = [dict(zip(a,i)) for i in set1]

Output:

[{'p': True, 'q': False, 'r': False, 's': False, 't': False},
 {'p': True, 'q': False, 'r': True, 's': True, 't': False},
 {'p': False, 'q': False, 'r': False, 's': False, 't': True},
 {'p': True, 'q': False, 'r': True, 's': False, 't': False},
 {'p': False, 'q': False, 'r': True, 's': True, 't': True},
 {'p': True, 'q': False, 'r': False, 's': True, 't': False},
 {'p': False, 'q': False, 'r': False, 's': True, 't': True},
 {'p': False, 'q': False, 'r': True, 's': False, 't': True},
 {'p': False, 'q': True, 'r': False, 's': False, 't': False},
 {'p': False, 'q': True, 'r': True, 's': True, 't': False},
 {'p': False, 'q': True, 'r': False, 's': True, 't': False},
 {'p': False, 'q': True, 'r': True, 's': False, 't': False},
 {'p': True, 'q': True, 'r': True, 's': False, 't': False},
 {'p': True, 'q': True, 'r': False, 's': True, 't': False},
 {'p': True, 'q': True, 'r': False, 's': False, 't': False},
 {'p': True, 'q': True, 'r': False, 's': False, 't': True},
 {'p': True, 'q': False, 'r': False, 's': True, 't': True},
 {'p': True, 'q': False, 'r': True, 's': False, 't': True},
 {'p': False, 'q': False, 'r': False, 's': True, 't': False},
 {'p': False, 'q': False, 'r': True, 's': False, 't': False},
 {'p': True, 'q': False, 'r': False, 's': False, 't': True},
 {'p': False, 'q': False, 'r': False, 's': False, 't': False},
 {'p': False, 'q': False, 'r': True, 's': True, 't': False},
 {'p': False, 'q': True, 'r': False, 's': True, 't': True},
 {'p': False, 'q': True, 'r': True, 's': False, 't': True},
 {'p': True, 'q': True, 'r': True, 's': True, 't': True},
 {'p': False, 'q': True, 'r': False, 's': False, 't': True}]
Sayandip Dutta
  • 15,602
  • 4
  • 23
  • 52