Python 我如何让一个函数在一个列表上迭代两次,从它停止的地方开始?
我正在制作一个Facebook Messenger机器人,它返回公交车到达指定站点的时间。到目前为止,机器人运行良好,但Facebook不允许机器人发送的消息超过320个字符。通常,机器人只能显示前5个左右,而不能超过此限制,这在非常繁忙的站点上是不够的 我有一个Python 我如何让一个函数在一个列表上迭代两次,从它停止的地方开始?,python,Python,我正在制作一个Facebook Messenger机器人,它返回公交车到达指定站点的时间。到目前为止,机器人运行良好,但Facebook不允许机器人发送的消息超过320个字符。通常,机器人只能显示前5个左右,而不能超过此限制,这在非常繁忙的站点上是不够的 我有一个if语句,它只显示前五个结果(如果停止超过该值),然后将结果传递给bot的send_message功能 我正在寻找一种方法,从5块单独的大型停止列表中获取结果,并让机器人在发送第一条消息后从停止的地方恢复。我目前的代码如下: if le
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
实际上是一个生成器,而不是一个常规函数(参见yield关键字)get_info
- 在
中,我借助get_info
函数将记录分组为itertools.groupby
组,该函数本身就是一个生成器groupu size
- 请注意,
是一个生成器对象,其中ascounter
将产生0、1、2、3、4、5、6、7、8。。。表达式next(counter)
将产生0,0,0,0,1,1,1,1,1,2。。。对于next(counter)//group_size
,这就是我们用来对记录进行分组的方法group\u size=5
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)
来使用下一条消息,迭代器内部状态将确保您不会处理同一条消息两次。@trincotsend_message
是一个普通函数。它从发送方获取消息的内容,并将其作为参数传递给总线公司的实时服务器。然后它会发送结果。您是否定期调用send_message
!起初,它无限期地重复,但那是我自己的错,我在那里留下了一个不必要的循环。不客气。我想知道为什么你没有回应。顺便说一句,我强烈建议您学习如何使用string.format()
方法,因为使用它比在代码中添加一组字符串更容易创建和打印输出。