Python 我如何让一个函数在一个列表上迭代两次,从它停止的地方开始?

Python 我如何让一个函数在一个列表上迭代两次,从它停止的地方开始?,python,Python,我正在制作一个Facebook Messenger机器人,它返回公交车到达指定站点的时间。到目前为止,机器人运行良好,但Facebook不允许机器人发送的消息超过320个字符。通常,机器人只能显示前5个左右,而不能超过此限制,这在非常繁忙的站点上是不够的 我有一个if语句,它只显示前五个结果(如果停止超过该值),然后将结果传递给bot的send_message功能 我正在寻找一种方法,从5块单独的大型停止列表中获取结果,并让机器人在发送第一条消息后从停止的地方恢复。我目前的代码如下: if le

我正在制作一个Facebook Messenger机器人,它返回公交车到达指定站点的时间。到目前为止,机器人运行良好,但Facebook不允许机器人发送的消息超过320个字符。通常,机器人只能显示前5个左右,而不能超过此限制,这在非常繁忙的站点上是不够的

我有一个
if
语句,它只显示前五个结果(如果停止超过该值),然后将结果传递给bot的
send_message
功能

我正在寻找一种方法,从5块单独的大型停止列表中获取结果,并让机器人在发送第一条消息后从停止的地方恢复。我目前的代码如下:

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)
如果len(信息[“结果])>5:
当我<5时:
n、 附加(“路由:“+”+str(信息['results'][i]['Route']])+”+“+”到“+”+str(信息['results'][i]['destination']]+”\n“+”到期:“+”+str(信息['results][i][“duetime”])+“+”分钟。”+“\n”)
i=i+1
其他:
而我

底部的
return
语句是传递给
send\u message
函数的语句。有什么方法可以实现多重消息方法吗?

下面是如何使用生成器和yield关键字实现这一点的示例代码-

def splitter(long_mess) :
        split_mess = ""
        for index in xrange(len(long_mess)) :
                if index>0 and index%5==0 :
                        yield split_mess
                        split_mess = ""
                split_mess += str(long_mess[index]) #replace with the n.append line
        yield split_mess

input = "This is a really long message"
ans = splitter(input)
for i in ans :
        print i #replace with send_message(i)
输出:

This 
is a 
reall
y lon
g mes
sage

下面是一个示例代码,它列出了包含5个站点信息的列表。然后,您可以在循环中调用
send\u message

def split_into_pairs_of_5(info)
    outer = []
    inner = []
    for x in range(len(info["results"])):
        if x % 5 == 0 and inner:
            outer.append(inner)
            inner = []

        inner.append("Route:" + " " + str(info['results'][i]['route']) + " " + "to" + " " + str(info['results'][i]['destination']) + "\n" + "Due:" + " " + str(info["results"][i]["duetime"]) + " " + "minutes." + "\n")

    if inner:
        outer.append(inner)
        inner = []

    return outer


result = split_into_pairs_of_5(info)

for i in info:
    send_message('\n'.join(str(x) for x in i))

通过在下面的代码中编写类似的
chunks()
,您可以轻松完成此任务:

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))
输出:

== CHUNK 1 ==
Route: 1 to DestA,
due in 1 minutes

Route: 2 to DestB,
due in 2 minutes

Route: 3 to DestC,
due in 3 minutes

Route: 4 to DestD,
due in 4 minutes

Route: 5 to DestE,
due in 5 minutes

== CHUNK 2 ==
Route: 6 to DestF,
due in 6 minutes

Route: 7 to DestG,
due in 7 minutes

Route: 8 to DestH,
due in 8 minutes
==CHUNK 1==
路线:1至德斯塔
截止时间:10分钟。
路线:2至目的地B
截止时间:20分钟。
路线:3至DestC
截止时间:30分钟。
路线:4至目的地
截止时间:40分钟。
路线:5到目的地
截止时间:50分钟。
==区块2==
路线:6至DestF
截止时间:60分钟。
路线:7至目的地
截止时间:70分钟。
路线:8至DestH
截止时间:80分钟。

我的方法使用
itertools.groupby()
将记录分组为5块(或任何正数)。在您的帖子中,您没有显示
send\u message
呼叫的名称,所以我自己给它命名:
get\u info

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
讨论
  • 对我来说,首要的任务不是如何解决这个问题,而是如何以一种友好、干净、易于理解的方式呈现记录,为此,我创建了函数
    show\u rec
    ,来完成这项工作
  • get_info
    实际上是一个生成器,而不是一个常规函数(参见yield关键字)
  • get_info
    中,我借助
    itertools.groupby
    函数将记录分组为
    groupu size
    组,该函数本身就是一个生成器
  • 请注意,
    counter
    是一个生成器对象,其中as
    next(counter)
    将产生0、1、2、3、4、5、6、7、8。。。表达式
    next(counter)//group_size
    将产生0,0,0,0,1,1,1,1,1,2。。。对于
    group\u size=5
    ,这就是我们用来对记录进行分组的方法

您可以将生成器函数与Python 2.7中的
range
(或
xrange
)一起使用,如下所示:

info = {'results': [
    {'route': 1, 'destination': 'DestA', 'duetime': '1'},
    {'route': 2, 'destination': 'DestB', 'duetime': '2'},
    {'route': 3, 'destination': 'DestC', 'duetime': '3'},
    {'route': 4, 'destination': 'DestD', 'duetime': '4'},
    {'route': 5, 'destination': 'DestE', 'duetime': '5'},
    {'route': 6, 'destination': 'DestF', 'duetime': '6'},
    {'route': 7, 'destination': 'DestG', 'duetime': '7'},
    {'route': 8, 'destination': 'DestH', 'duetime': '8'},
]}


def iter_with_chunks(seq, chunk_size):
    for index in range(0, len(seq), chunk_size):
        yield seq[index: index + chunk_size]


for count, chunk in enumerate(iter_with_chunks(info["results"], 5), 1):
    print("== CHUNK {count} ==".format(count=count))
    for item in chunk:
        output = 'Route: {route} to {destination},\n' \
                 'due in {duetime} minutes\n'.format(**item)
        print(output)
输出:

== CHUNK 1 ==
Route: 1 to DestA,
due in 1 minutes

Route: 2 to DestB,
due in 2 minutes

Route: 3 to DestC,
due in 3 minutes

Route: 4 to DestD,
due in 4 minutes

Route: 5 to DestE,
due in 5 minutes

== CHUNK 2 ==
Route: 6 to DestF,
due in 6 minutes

Route: 7 to DestG,
due in 7 minutes

Route: 8 to DestH,
due in 8 minutes

send\u message
是普通函数还是类的成员?
info
是在这个函数中创建的,还是作为参数传递给它的?这似乎是生成器的一个主要示例。没有足够的代码来编写全面的答案,但是调用
my_iter=iter(my_list)
?。之后,您可以调用
next(my_iter)
来使用下一条消息,迭代器内部状态将确保您不会处理同一条消息两次。@trincot
send_message
是一个普通函数。它从发送方获取消息的内容,并将其作为参数传递给总线公司的实时服务器。然后它会发送结果。您是否定期调用
send_message
!起初,它无限期地重复,但那是我自己的错,我在那里留下了一个不必要的循环。不客气。我想知道为什么你没有回应。顺便说一句,我强烈建议您学习如何使用string
.format()
方法,因为使用它比在代码中添加一组字符串更容易创建和打印输出。