Ryan Werner Ryan Werner - 2 months ago 8
Python Question

How do I make a function iterate over a list twice, picking up where it left off?

I'm making a Facebook Messenger bot which returns the times of buses coming to a specified stop. So far, the bot is working fine, but Facebook doesn't allow for messages sent by bots to be over 320 characters. Often, the bot can only display the first 5 or so without going over this limit, which isn't good enough at very busy stops.

I have an

if
statement in place which only shows the first five results if the stop has more than that, and then passes the results to the bot's
send_message
function.

I'm looking for a way to get the results from large stop lists in separate chunks of 5, and have the bot pick up where it left off, after sending the first message. My current code is as follows:

if len(info["results"]) > 5:
while i < 5:
n.append("Route:" + " " + str(info['results'][i]['route']) + " " + "to" + " " + str(info['results'][i]['destination']) + "\n" + "Due:" + " " + str(info["results"][i]["duetime"]) + " " + "minutes." + "\n")
i = i + 1
else:
while i < len(info["results"]):
n.append("Route:" + " " + str(info['results'][i]['route']) + " " + "to" + " " + str(info['results'][i]['destination']) + "\n" + "Due:" + " " + str(info["results"][i]["duetime"]) + " " + "minutes." + "\n")
i = i + 1

return '\n'.join(str(x) for x in n)


The
return
statement at the bottom is what is getting passed to the
send_message
function. Is there any way I can achieve the multiple message method?

Answer

You can do it easily by writing a generator function like chunks() in the code below:

info = {'results': [
            {'route': 1, 'destination': 'DestA', 'duetime': '10'},
            {'route': 2, 'destination': 'DestB', 'duetime': '20'},
            {'route': 3, 'destination': 'DestC', 'duetime': '30'},
            {'route': 4, 'destination': 'DestD', 'duetime': '40'},
            {'route': 5, 'destination': 'DestE', 'duetime': '50'},
            {'route': 6, 'destination': 'DestF', 'duetime': '60'},
            {'route': 7, 'destination': 'DestG', 'duetime': '70'},
            {'route': 8, 'destination': 'DestH', 'duetime': '80'},
            ],
       }

def chunks(info, n):
    results = info['results']
    for i in range(0, len(results), n):
        chunk = [
            'Route: {} to {}\nDue: {} minutes.\n'.format(
                result['route'], result['destination'], result["duetime"])
                    for result in results[i:i+n]]
        yield '\n'.join(chunk)

for i, chunk in enumerate(chunks(info, 5), 1):
    print('== CHUNK {} ==\n{}'.format(i, chunk))

Output:

== CHUNK 1 ==
Route: 1 to DestA
Due: 10 minutes.

Route: 2 to DestB
Due: 20 minutes.

Route: 3 to DestC
Due: 30 minutes.

Route: 4 to DestD
Due: 40 minutes.

Route: 5 to DestE
Due: 50 minutes.

== CHUNK 2 ==
Route: 6 to DestF
Due: 60 minutes.

Route: 7 to DestG
Due: 70 minutes.

Route: 8 to DestH
Due: 80 minutes.