我需要一个python函数,它将采用以下形式的字符串列表:
seq = ['A[0]','B[2:5]','A[4]']
并返回"扩展"的新列表具有保留顺序的元素,如下所示:
expanded = ['A[0]', 'B[2]', 'B[3]', 'B[4]', 'B[5]', 'A[4]']
为了实现我的目标,我写了这个简单的函数:
def expand_seq(seq):
#['item[i]' for item in seq for xrange in item]
return ['%s[%s]'%(item.split('[')[0],i) for item in seq for i in xrange(int(item.split('[')[-1][:-1].split(':')[0]),int(item.split('[')[-1][:-1].split(':')[-1])+1)]
当处理产生少于500k项目的序列时,它运行良好,但是当生成非常大的列表(超过100万)时它会减慢很多。例如:
# let's generate 10 million items!
seq = ['A[1:5000000]','B[1:5000000]']
t1 = time.clock()
seq = expand_seq(seq)
t2 = time.clock()
print round(t2-t1, 3)
# RESULT: 9.541 seconds
我正在寻找改进此功能的方法,并希望在处理大型列表时加快速度。如果有人有建议,我很乐意听到他们的意见!
答案 0 :(得分:2)
以下似乎可以提供35%的加速:
import re
r = re.compile(r"(\w+)\[(\d+)(?::(\d+))?\]")
def expand_seq(seq):
result = []
for item in seq:
m = r.match(item)
name, start, end = m.group(1), int(m.group(2)), m.group(3)
rng = xrange(start, int(end)) if end else (start,)
t = name + "["
result.extend(t + str(i) + "]" for i in rng)
return result
使用此代码:
答案 1 :(得分:0)
我不确定您是否会获得戏剧加速,因为您无法从根本上改进算法。通过这种方式,我确实获得了大约20%的加速:
def expand_seq(seq):
expanded = []
for s in seq:
name, indices = s[0:-1].split("[")
if ":" in indices:
index1, index2 = [int(i) for i in indices.split(":")]
else:
index1 = int(indices)
index2 = index1
for n in range(index1, index2 + 1):
expanded.append("{}[{}]".format(name, n))
return expanded
我认为加速很大程度上是由于不重复某些操作(例如int
和split
),您必须这样做才能将解决方案保持为单行。
如上所述,如果您使用生成器,您可以立即开始使用结果。像这样:
def expand_seq(seq):
for s in seq:
name, indices = s[0:-1].split("[")
if ":" in indices:
index1, index2 = [int(i) for i in indices.split(":")]
else:
index1 = int(indices)
index2 = index1
for n in range(index1, index2 + 1):
yield "{}[{}]".format(name, n)