0

I am trying to find if there is a more efficient way of finding these combinations using some Python scientific library.

I am trying to avoid native for loops and list append preferring to use some NumPy or similar functionality that in theory should be more efficient given it's using C code under the hood. I am struggling to find one, but to me this is quite a common problem to make these operations in an efficient way rather than using slow Python native structures.

I am wondering if I am looking in the wrong places? E.g. this does not seem to help here: https://docs.scipy.org/doc/numpy-1.15.0/reference/generated/numpy.random.binomial.html

See here I am taking the binomial coefficients of a list of length 5 starting from a lower bound of 2 and finding out all the possible combinations. Meanwhile I append to a global list so I then have a nice list of "taken items" from the original input list.

import itertools

input_list = ['a', 'b', 'c', 'd', 'e']

minimum_amount = 2

comb_list = []
for i in range(minimum_amount, len(input_list)):
    curr_list = input_list[:i+1]
    print(f"the current index is: {i}, the lists are: {curr_list}")
    curr_comb_list = list(itertools.combinations(curr_list, i))
    comb_list = comb_list + curr_comb_list
print(f"found {len(comb_list)} combinations (check on set length: {len(set(comb_list))})")
print(comb_list)

Gives:

found 12 combinations (check on set length: 12)
[('a', 'b'), ('a', 'c'), ('b', 'c'), ('a', 'b', 'c'), ('a', 'b', 'd'), 
('a', 'c', 'd'), ('b', 'c', 'd'), ('a', 'b', 'c', 'd'), ('a', 'b', 'c', 'e'), 
('a', 'b', 'd', 'e'), ('a', 'c', 'd', 'e'), ('b', 'c', 'd', 'e')]
  • Is it possible to do this avoiding the for loop and using some scientific libraries to do this quicker?
  • How can I do this in a quicker way?
TPPZ
  • 4,447
  • 10
  • 61
  • 106

2 Answers2

2

The final list contains all combinations of any length from 1 to len(input_list), which is actually the Power Set.
Look at How to get all possible combinations of a list’s elements?.

Aviv Yaniv
  • 6,188
  • 3
  • 7
  • 22
  • Yeah, sorry I meant to have a "take 2" as a parameter like `minimum_amount`. I've updated the question. – TPPZ Aug 23 '20 at 12:44
1

You want all combinations from input_list of length 2 or more.

To get them, you can run:

comb_lst = list(itertools.chain.from_iterable(
    [ itertools.combinations(input_list, i)
        for i in range(2, len(input_list)) ]))

Something similiar to powerset in examples in the itertools web site, but not exactly the same (the length starts from 2, not from 1).

Note also that curr_list in your code is actually used only for printing.

Valdi_Bo
  • 30,023
  • 4
  • 23
  • 41
  • Thanks, I just updated the code snippet using `curr_list` inside the `for` loop. The "take 2" is to be considered a parameter like `minimum_amount`. – TPPZ Aug 23 '20 at 12:43