0

How can I use

itertools.combinations_with_replacement

by leaving out some particular type of combinations. In the case

list(combinations_with_replacement([1, 2, 3, 4], 3))

I need to avoid (1,1,1), (2,2,2), (3,3,3), (4,4,4) by leaving all the rest. Here is a good reference, but I could not find what I need.

Kalin Stoyanov
  • 587
  • 2
  • 5
  • 10

2 Answers2

1

You may combine itertools.combinations_with_replacement() with a simple filter() function:

combinations = combinations_with_replacement([1, 2, 3, 4], 3)
filtered = filter(lambda c: len(set(c)) > 1, combinations)

You are in charge of selecting which combinations should be filtered or not. Here using a lambda function: if all elements are the same, discard it.

Delgan
  • 18,571
  • 11
  • 90
  • 141
  • It works and gave exactly what I needed, THNK YOU !! But I have no idea how it works, where I can read bout this filter? – Kalin Stoyanov Aug 25 '19 at 17:41
  • 1
    @kalinfirst You may look at the documentation page I linked. Basically, `filter()` needs two arguments. The first one is a function which return `True` if the element is accepted, `False` if it should be discarded. The second argument is the list of element on which the filtering function should be applied. – Delgan Aug 25 '19 at 17:46
  • In fact my question should be why "len(set(c)) > 1" remove the triple combinations – Kalin Stoyanov Aug 25 '19 at 17:47
  • 1
    @kalinfirst Oh sorry. So, for example if `c == (1, 2, 3)` then `set(c) == {1, 2, 3}` and `len(set(c)) == 3`, so this combination if accepted. However, if `c == (1, 1, 1)` then `set(c) == {1}` so it is discarded. Sets are non-ordered data structures which stores elements different from each others. Once the combination `(1, 1, 1)` is transformed to a set `{1}`, it's easy to see if all elements of the combination were the same. – Delgan Aug 25 '19 at 17:54
1

If the input list is sorted or contains distinct elements, this would also yield the intended result:

combinations = combinations_with_replacement([1, 2, 3, 4], 3)
filtered = (c for c in combinations if c[0] != c[-1])  # Use square brackets if a list is needed

The solution works because in each generated combination tuple, elements are sorted according to their indices in the input list. Therefore if c[0] == c[-1], then for any element e such that index(c[0])<=index(e)<=index(c[-1]), c[0]==e==c[-1] holds according to the constraint of the input.

GZ0
  • 4,055
  • 1
  • 10
  • 21