-2

how to generate the following list from the following dictionary

d = {2: 4, 3: 1, 5: 3}

f = [
    2**1,2**2, 2**3, 2**4, 3**1, 5**1, 5**2, 5**3, 
    2**1 * 3, 2**2 * 3, 2**3 * 3, 2**4 * 3, 5**1 * 3, 5**2 * 3, 5**3 * 3, 
    2**1 * 5, 2**2 * 5, 2**3 * 5, 2**4 * 5, 
    2**1 * 5**2, 2**2 * 5**2, 2**3 * 5**2, 2**4 * 5**2, 3**1 * 5**2, 
    2**1 * 5**3, 2**2 * 5**3, 2**3 * 5**3, 2**4 * 5**3, 3**1 * 5**3, 
    2**1 * 3**1 * 5**1, 2**1 * 3**1 * 5**2, 2**1 * 3**1 * 5**3, 
    2**2 * 3**1 * 5**1, 2**2 * 3**1 * 5**2, 2**2 * 3**1 * 5**3, 
    2**3 * 3**1 * 5**1, 2**3 * 3**1 * 5**2, 2**3 * 3**1 * 5**3, 
    2**4 * 3**1 * 5**1, 2**4 * 3**1 * 5**2, 2**4 * 3**1 * 5**3, 
    ]

Moreover I want to expand for more general case ie dictionary of k key-value pairs

Edit: Explanation of the pattern: Each key is raised to power of 0 to it's value and after that for each of those terms we do combination with similar terms from other keys.

I can think of doing so in recursive ways. Any non recusive approach is welcome.

PS: Order is not important

ishandutta2007
  • 16,676
  • 16
  • 93
  • 129

1 Answers1

6

One way, expanding the list with each possible factor and its powers:

f = [1]
for k, v in d.items():
    f += [x * k**i
          for x in f 
          for i in range(1, v+1)]

Perhaps faster, repeatedly multiplying with the factor instead of computing powers:

f = [1]
for k, v in d.items():
    g = f
    for _ in range(v):
        g = [x * k for x in g]
        f += g

Somewhat tricky version of that which is short and I believe fast (confirmed by OP in the comments):

from itertools import islice, repeat
from operator import mul

f = [1]
for k, v in d.items():
    f += map(mul, repeat(k, len(f) * v), f)

A completely different way, first computing the powers for each factor and then using itertools.product and math.prod to combine them:

from itertools import product, accumulate, repeat
from math import prod

f = list(map(prod, product(*[[k**i for i in range(v+1)]
                             for k, v in d.items()])))

All include the number 1 in the list. If that's a problem, just remove it.

Kelly Bundy
  • 23,480
  • 7
  • 29
  • 65