How do I make a function iterate over a list twice, picking up where it left off?
<p>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.</p>

<p>I have an <code>if</code> 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 <code>send_message</code> function.</p>

<p>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:</p>

<pre><code>if len(info["results"]) &gt; 5:
    while i &lt; 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 &lt; 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)
</code></pre>

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

<p>My approach uses <code>itertools.groupby()</code> to group the records in chunk of 5 (or any positive number). In your post, you are not showing the name in which <code>send_message</code> calls, so I just name it myself: <code>get_info</code>:</p>

<pre><code>import itertools

def show_rec(rec):
    output = 'Route: {route} to {destination}, due in {duetime} minutes'.format(**rec)
    return output

def get_info(group_size=5):
    # Do something to get info
    counter = itertools.count()
    for _, group in itertools.groupby(info['results'], key=lambda v: next(counter) // group_size):
        yield '\n'.join(show_rec(r) for r in group)

# Here is inside function send_message
for output in get_info(group_size=5):
    print output
    print
</code></pre>

<h1>Discussion</h1>

<ul>
<li>The first order of business for me is not how to solve this problem, but how to present a record in a nice, clean, and easy-to-understand manner, for that, I created the function <code>show_rec</code> to do the job</li>
<li><code>get_info</code> is really a generator, not a regular function (see the yield keyword)</li>
<li>Inside <code>get_info</code>, I group the records in group of <code>group_size</code> with the help of the <code>itertools.groupby</code> function, which itself is a generator.</li>
<li>Note that <code>counter</code> is a generator object where as <code>next(counter)</code> will yield 0, 1, 2, 3, 4, 5, 6, 7, 8, ... The expression <code>next(counter) // group_size</code> will yield 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, ... for <code>group_size=5</code> and that is what we use to group the records.</li>
</ul>

python