高效使用Python的lambda和map的方法
我需要在Bigtable(数据库)中存储一个很大的整数列表。为了提高效率,我把这些整数存储成相邻两个数字之间的差值。
比如:
original_list = [1005, 1004, 1003, 1004, 1006]
上面这个列表(实际上包含超过100万个项目)被存储成:
start = 1005 diff = [-1, -1, 1, 2]
我目前能做到的最接近的方式是:
ltp = [start] map(lambda x: ltp.append(ltp[-1] + x), tick)
我在寻找一种高效的方法,把它转换回原来的列表。
9 个回答
4
非常适合生成器:
def diff2abs( diffs, start ):
yield start
for diff in diffs:
start += diff
yield start
start = 1005
diffs = [-1, -1, 1, 2]
original_list = list( diff2abs( diffs, start ))
7
对于这么大的数据结构,使用numpy会非常有效。在这个例子中,它的速度快了超过200倍(见下文),而且编码起来也简单一些,基本上只需要这样做:
add.accumulate(diff)
下面是numpy和直接操作列表的比较:
import numpy as nx
import timeit
N = 10000
diff_nx = nx.zeros(N, dtype=nx.int)
diff_py = list(diff_nx)
start = 1005
def f0():
orig = [start]
for x in diff_py:
orig.append(orig[-1] + x)
def f1():
diff_nx[0] = start
nx.add.accumulate(diff_nx)
t = timeit.Timer("f0()", "from __main__ import f0, f1, diff_nx, diff_py, nx, start")
print t.timeit(number=1000)
t = timeit.Timer("f1()", "from __main__ import f0, f1, diff_nx, diff_py, nx, start")
print t.timeit(number=1000)
结果是:
13.4044158459 # for list looping
0.0474112033844 # for numpy accumulate
其实,使用一个已经成熟的压缩算法会更好,比如可以轻松使用的PyTables,而不是像你现在这样自己去实现一个。
另外,我建议你在读取数据时留出空间给前面的起始项,而不是重新构建一个包含起始项的列表,这样你就不需要进行复制了。
6
以下内容对我有效:
orig = [start]
for x in diff:
orig.append(orig[-1] + x)
使用 map
会创建一个新的数组,大小和原来的数组一样,但里面全是 None
。我觉得用简单的 for
循环更容易理解,而且在这种情况下速度也差不多。