12major e
12major e

Reputation: 49

Iterating over a Python generator

I'm trying to write a function that will take as input a string of intervals e.g "0-0,4-8,20-21,43-45" to produce all numbers within each of the ranges meaning: [0, 4, 5, 6, 7, 8, 20, 21, 43, 44, 45]

The exercise requires to do so using generators. I managed to parse the input through a generator but I can't do the same for populating the numbers. I'm trying to int() each number so I could leverage the range() to produce all numbers within the edges.

Here's my conceptual code - how can I produce the numbers within each interval?

def parse_ranges(arg):
    arg = arg.split(",")
    parsed= (line.split("-") for line in arg)

    #Trying to parse each character to int to use range()
    intervals= (int(i) for i in number for number in parsed)

    # Even if I had the characters parsed to int, I still don't know how to produce the range
    ranges = (range(interval[0],interval[1]) interval for interval in intervals)
    return ranges

print(list(parse_ranges("0-0,4-8,20-21,43-45")))

Upvotes: 0

Views: 107

Answers (2)

sql_knievel
sql_knievel

Reputation: 1369

def parse_ranges(arg):
    arg = arg.split(",")
    parsed = ((line.split("-")) for line in arg)

    for pair in parsed:
        yield from range(int(pair[0]), int(pair[1])+1)

print(list(parse_ranges("0-0,4-8,20-21,43-45")))

Out: [0, 4, 5, 6, 7, 8, 20, 21, 43, 44, 45]

If you want to pass values from a generator INSIDE another generator directly out to the consumer of the outer generator, you need to use the "yield from" expression. (Also, note that you need to extend the "to" end of each range by +1, since the range endpoint is not inclusive.)

Upvotes: 2

cdlane
cdlane

Reputation: 41872

Two pieces that you seem to missing are: the second argument of range() needs to be one beyond what you want; you can pass control from one generator to another via yield from:

def parse_ranges(arg):
    for start, stop in (interval.split('-') for interval in arg.split(',')):
        yield from range(int(start), int(stop) + 1)

print(*parse_ranges("0-0,4-8,20-21,43-45"))

OUTPUT

% python3 test.py
0 4 5 6 7 8 20 21 43 44 45
%

Upvotes: 0

Related Questions