高效使用Python的lambda和map的方法

3 投票
9 回答
7991 浏览
提问于 2025-04-15 14:00

我需要在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 循环更容易理解,而且在这种情况下速度也差不多。

撰写回答