1

I have this function g() my goal is to yield a result similar to product() but with constrained number of appearance for each group of characters. So in the code below instead of doing product(a, repeat=3) g() is supposed to yield all the combinations where characters from a appear 2 times and characters from b appear 1 time. Here is what I have :

from itertools import permutations, product

a='ABC'
b=['*', '%3A']
l=[a]*2+[b]

def g(list):
    for p in permutations(list):
        yield product(*p)


result=g(l)

So the problem I'm facing is that when I yield the result I got a nested iterator that is painful to use and when I use return it just returns the generator corresponding to only the first loop turn, just as if I did : g() only consisted of def g(): return product(*next(permutations(list))).

Steven Rumbalski
  • 44,786
  • 9
  • 89
  • 119
ChiseledAbs
  • 1,963
  • 6
  • 19
  • 33
  • Think about what you would do if you weren't writing a `g` generator, and you just wanted to call `some_function(x)` on every combination. Write that code, and then replace `some_function` with `yield`. – user2357112 Jan 03 '17 at 18:34
  • @snakecharmerb python 3, oh yes you're right there is `yield from` I totally forgot, I solved the problem using `c=chain(c,product(*p))` and returning c at the end, had the idea just after posting that. – ChiseledAbs Jan 03 '17 at 18:42
  • 1
    I noticed that if I do `result=sorted(map(list, g(l)))` that `all(result[i] == result[i+1] for i in range(0, 6, 2))` is `True`. In other words, it seems you get two identical sets of results. Do you want that? – Steven Rumbalski Jan 03 '17 at 18:49
  • @StevenRumbalski you're right thanks for the observation, is there a way to avoid `permutations()` to generate identical lists in the same generator ? – ChiseledAbs Jan 03 '17 at 18:58
  • If the current behavior is what you want, I wouldn't change anything. Or am I misunderstanding? – Steven Rumbalski Jan 03 '17 at 19:24
  • @StevenRumbalski I mean you're right about that being a problem, I definitely don't want to iterate multiple times through the same elements for my main problem. It's due to the fact that `permutations()` is generating identical lists if fed with a list containing some identical elements. I wonder if you know a solution to avoid that. – ChiseledAbs Jan 03 '17 at 19:34
  • See the answer to [permutations with unique values](http://stackoverflow.com/questions/6284396/permutations-with-unique-values). – Steven Rumbalski Jan 03 '17 at 21:25
  • 1
    Or use `from sympy.utilities.iterables import multiset_permutations` which may be more efficient. – Steven Rumbalski Jan 03 '17 at 21:32
  • Or use [`more_itertools.distinct_permutations(iterable)`](https://more-itertools.readthedocs.io/en/latest/api.html#more_itertools.distinct_permutations). – Steven Rumbalski Jan 03 '17 at 21:40
  • @StevenRumbalski incredible, with every other solutions I was met with `unashable type list` but the sympy package worked like a charm, thanks a lot for your help ! – ChiseledAbs Jan 03 '17 at 21:57

1 Answers1

3

If you are python 3.3 or later you can use PEP 380: Syntax for Delegating to a Subgenerator ... just do yield from

from itertools import permutations, product

a='ABC'
b=['*', '%3A']
l=[a]*2+[b]

def g(list):
    for p in permutations(list):
        yield from product(*p)


result=g(l)
tdelaney
  • 73,364
  • 6
  • 83
  • 116