Search code examples
pythoniteratorcombinationspermutation

How to get generator function to print


Edit: I saw a post about including brackets to make a list. In this case, where would I insert said brackets? Sorry, newbie.

I have a function to generate combinations of any given number range but I need to print out or list all the possible combinations. Instead I'm getting this:

<generator object combinations at 0x00000175A6796040>

The source code:

def combinations(iterable,r):
    pool = tuple(iterable)
    n = len(pool)
    if r > n:
        return
    indices = list(range(r))
    yield tuple(pool[i] for i in indices)
    while True:
        for i in reversed(range(r)):
            if indices[i] !=i + n - r:
                break
        else:
            return
        indices[i] += 1
        for j in range(i+1,r):
            indices[j] = indices[j-1] + 1
        yield tuple(pool[i] for i in indices)

combinations(range(4),5)

I would like a list of all number combinations from 0 to 4 in 5-digit numbers. How do I call the function in a way that allows me to view the actual combinations?


Solution

  • Generators and iterators are lazily evaluated functions, hence the use of the yield keyword. Therefore, to get the next value from a generator or iterator, say gen, we call next(gen). Some other comments on your post are saying that you should just cast your generator to a list, which is fine but may defeat the purpose of using a generator.

    Additionally, your code won't produce anything if you call next() or cast to a list. This is because you check for if r > n, which it is when range(4) and 5 are passed in as arguments. Ultimately, you code immediately exits your function.

    If you wish for your code to output all combinations as 5 digit numbers given your input, you're code must allow for repeat digits in the output combinations.

    Therefore, rather use:

    def combinations(iterable,r):
        pool = tuple(iterable)
        start = tuple(pool[0] for i in range(r))
        yield start
        while True:
            for i in reversed(range(r)):
                if start[i] != pool[-1]:
                    break
            else:
                return
            start = list(start)
            start[i] = pool[pool.index(start[i])+1]
            for j in range(i+1,r):
                start[j] = pool[0]
            yield tuple(start)
    

    To call and get all combinations do either of the following:

    gen = combinations(range(4),5)
        while True:
            try:
                print(next(gen))
            except StopIteration:
                break
    

    , or

    gen = combinations(range(4),5)
    list(gen)
    

    , or

    for i in combinations(range(4),5):
        print(i)