一、问题的由来
之前,我写过一篇调用同花顺机器翻译api,批量翻译字幕的文章。
在调用机器翻译api过程中,我遇到一个问题,就是网站给的Python样例代码中只接收字符长度少于5000的列表,所以我想,如果我们一句一句把句子传给服务器翻译,那么程序的运行速度一定会很慢,如果我们把由30~50个字符串元素组成的列表传递给翻译服务器,运行效率一定会大大提高。
但是,如何进行列表元素分组,并且保证字符串的总长度少于5000,一直是困扰我的难题。今天我一直找到了答案。
二、问题的解决
上面的问题,我简化为如下问题:把一个列表中的元素自定义分组,然后判断分组后的字符串长度是否小于一定长度。
为了进一步加快程序运行速度,简化算法,我们先定义一个函数,函数接受一个列表和一个整数。
def chunks(lst:list,n:int):
for i in range(0,len(lst),n):
yield lst[i:i+n]
列表是要分组的列表,整数是分组后元素的个数。为了加快程序执行速度,我们定义参数时,直接声明了参数的类型,如lst参数是列表,n是整数型,同时在函数中用yield直接给出解决,而不是在遍历结束后给出结果,也就是用生成器取代了列表,加快了程序的执行速度。
然后,我们再定义一个sample,来应用上这个程序:
def chunks(lst:list,n:int):
for i in range(0,len(lst),n):
yield lst[i:i+n]
sample:list[str] = ['a','b','c','d','e']
new = list(chunks(sample,3))
print(new)
最终我们把返回的生成器再转化为列表,结果就是:
[['a', 'b', 'c'], ['d', 'e']]
三、问题的深入
分组成功后,我们就可以遍历新的列表new,然后把新的分组列表传给远程服务器,进行机器翻译。
如果还要加上判断是否字符长度小于5000,可以用下面的代码。
for li in new:
if len(" ".join(li))<5000:
translate(api, li) #这里假定翻译函数名是translate()
实现这些任务后,我们还可以继续深入分析,如果把这些分组元素再重复2次,简单的说就是把下面的列表:
[['a', 'b', 'c'], ['d', 'e']]
变成下面的列表
['a','b','c','a','b','c','d', 'e','d', 'e']
并且展开成一个列表怎么操作呢?其实我们可以借用之前用到的方法,
最终我们得到以下代码:
def chunks(lst:list,n:int):
for i in range(0,len(lst),n):
yield lst[i:i+n]
sample:list[str] = ['a','b','c','d','e']
new = list(chunks(sample,3))
print([elm for i in new for elm in i*2])
生成的结果:
在以上代码中,我们用列表推导式把列表元素重复2遍,并展开所有子列表。如果是列表元素重复2次,把列表推导式中的i变成[i],这样就可以实现子列表的重复。
print([elm for i in new for elm in [i]*2])
四、学后反思
- 可以通过声明变量类型、使用生成器、列表推导式等方法可以简化算法,加快程序的运行速度。
- 变量声明又上了新高度,声明一个列表变量用:sample:list[str] = ['1','2','3'],直接规定变量类型为列表,而且列表中的元素类型也规定为字符。