删除列表中条目的最有效方法

Most efficient way to remove entries in a list

我有一个庞大的 4D 数据集,分布在 4 个变量中,x_listy_listz_listi_list。每个都是 N 个标量的列表,X、Y 和 Z 代表点在 space 中的位置,I 代表强度。

我已经有一个功能可以通过将强度设置为 0 来挑选并标记可忽略的点(强度太低的点)以进行删除。但是,当我 运行 在我的 200 万点集,删除过程需要几个小时。

目前,我正在使用 .pop(index) 命令删除数据点,因为它做得非常干净。这是代码:

counter = 0
i = 0
for entry in i_list
    if (i_list[i] == 0):
        x_list.pop(i)
        y_list.pop(i)
        z_list.pop(i)
        i_list.pop(i)
        counter += 1
        print (counter, "points removed")
    else
        i += 1

我怎样才能更有效地做到这一点?

我认为为每个现有列表创建新的空列表并在 i_list[i] != 0 中附加项目会更快。查找您正在执行的操作的 time complexity,您会发现删除项目是 O(n),而追加是 O(1)。当前,您正在执行 lot 的 O(n) 删除操作,并且 n 相当大,这将非常慢。

所以像这样:

new_x = []
new_y = []
new_y = []
new_i = []

for index in range(len(i_list)):
    if i_list[index] != 0:
        new_x.append(x_list[index])
        new_y.append(y_list[index])
        # Etc.

更进一步,您应该研究 numpy 数组,其中子集化以找到 i_list != 0 所在的项目集会非常快。

你应该使用 del:

array = [1, 2, 3]
del array[0]

给出:[2, 3]

最重要的是,在遍历大文件时使用 print() 无异于自杀。大部分时间都花在了打印上。示例如下:

>>> from time import time
>>> def test1(n):
...     for i in range(n):
...             print(i)
... 
>>> def test2(n):
...     for i in range(n):
...             i += 1
...
>>> def wraper():
...     t1 = time()
...     test1(1000)
...     t2 = time()
...     test2(1000)
...     t3 = time()
...     print("Test1: %s\ntest2: %s: " % (t2-t1, t3-t2))

输出为:

(lots of numbers)
Test1: 0.46030712127685547
test2: 0.0:

这是一个快乐列表理解的工作!

x_prime_list = [x for (index, x) in enumerate(x_list) 
                  if i_list[index] != 0]

使用 enumerate()x_list 的成员与其序号地址配对。当且仅当 i_list[index] 不为零时,它将所有成员 x 放入新列表(否则它不会向列表添加任何内容。

与您发布的等效代码相比,列表理解的优势在于循环和追加是在 C 中处理的,而不需要 Python 来完成这些任务。