我正在制作一个Facebook Messenger机器人,它返回指定停靠点的公交车次数。到目前为止,机器人工作正常,但Facebook不允许机器人发送的消息超过320个字符。通常情况下,机器人只能显示前5个左右而不超过此限制,这在非常繁忙的停留时间不够好。
我有一个if
语句,如果停止次数多于此值,则只显示前五个结果,然后将结果传递给机器人的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)
底部的return
语句是传递给send_message
函数的内容。有什么方法可以实现多重消息方法吗?
答案 0 :(得分:4)
您可以通过在下面的代码中写generator function 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: 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.
答案 1 :(得分:1)
以下是使用generator和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
答案 2 :(得分:0)
下面是一个示例代码,它列出了包含大约5个停靠点的信息的列表。然后,您可以在循环中调用send_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))
答案 3 :(得分:0)
我的方法使用itertools.groupby()
将记录分组为5(或任何正数)。在您的帖子中,您没有显示send_message
来电的姓名,因此我只是自己命名:get_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_rec
做这份工作get_info
实际上是一个生成器,而不是常规函数(请参阅yield关键字)get_info
内,我借助group_size
函数将itertools.groupby
组中的记录分组,counter
函数本身就是一个生成器。next(counter)
是一个生成器对象,其中next(counter) // group_size
将产生0,1,2,3,4,5,6,7,8 ......表达式{{1}将为group_size=5
产生0,0,0,0,1,1,1,1,1,2,2 ......,这就是我们用来对记录进行分组的内容。答案 4 :(得分:0)
您可以使用range
(或Python 2.7中的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