从Python 2D列表中删除列的最佳/最快方法

时间:2019-02-03 13:20:34

标签: python python-3.x list filter

我在python中有一个列表列表的列表(所有列表的大小均相同):

A = [[1,2,3,4],['a','b','c','d'] , [12,13,14,15]]

我要删除一些列(所有列表的第i个元素)。

没有for语句,有没有办法做到这一点?

5 个答案:

答案 0 :(得分:5)

如前所述,没有循环就无法做到这一点。但是,使用内置函数是一种不显式使用任何循环的函数方法:

In [24]: from operator import itemgetter

In [25]: def remove_col(arr, ith):
    ...:     itg = itemgetter(*filter((ith).__ne__, range(len(arr[0]))))
    ...:     return list(map(list, map(itg, arr)))
    ...: 

演示:

In [26]: remove_col(A, 1)
Out[26]: [[1, 3, 4], ['a', 'c', 'd'], [12, 14, 15]]

In [27]: remove_col(A, 3)
Out[27]: [[1, 2, 3], ['a', 'b', 'c'], [12, 13, 14]]

请注意,如果您仅返回list(map(list, map(itg, arr)))而不是map(itg, arr),它将为您带来预期的结果,但它是迭代器的迭代器,而不是列表列表。在这种情况下,这将是一种在内存和运行时方面都更优化的方法。

此外,使用循环是我这样做的方式:

In [31]: def remove_col(arr, ith):
    ...:     return [[j for i,j in enumerate(sub) if i != ith] for sub in arr]

令人惊讶的是(如果您不相信C的强大功能,那么)对于大型数组,该功能方法甚至更快。

In [41]: arr = A * 10000

In [42]: %timeit remove_col_functional(arr, 2)
8.42 ms ± 37.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [43]: %timeit remove_col_list_com(arr, 2)
23.7 ms ± 165 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

# And if in functional approach you just return map(itg, arr)
In [47]: %timeit remove_col_functional_iterator(arr, 2)
1.48 µs ± 4.71 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

答案 1 :(得分:3)

我认为,如果您精通word(这是我最喜欢的“ hack”),则可以不用for来做到这一点:

zip

结果(i = 2):

A = [[1, 2, 3, 4], ['a', 'b', 'c', 'd'], [12, 13, 14, 15]]
B = list(zip(*A))
B.pop(i)
C = list(map(list, zip(*B)))

当然,[[1, 2, 4], ['a', 'b', 'd'], [12, 13, 15]] 是列表理解的替代方法:

map

答案 2 :(得分:3)

numpy可以删除整列:

import numpy

A = [[1,2,3,4],['a','b','c','d'] , [12,13,14,15]]

na = numpy.array(A)

print(na[:,:-1])   # remove last column
print(na[:,1:])    # remove first column

print(numpy.concatenate((na[:,:2],na[:,3:]),axis=1)) # build from 2 slices: remove third column

结果(为简单起见:所有数据均已转换为字符串,不涉及dtype):

[['1' '2' '3']
 ['a' 'b' 'c']
 ['12' '13' '14']]

[['2' '3' '4']
 ['b' 'c' 'd']
 ['13' '14' '15']]

[['1' '2' '4']
 ['a' 'b' 'd']
 ['12' '13' '15']]

答案 3 :(得分:3)

另一种使用列表理解的变体,带有enumerate

>>> A = [[1,2,3,4],['a','b','c','d'] , [12,13,14,15]]
>>> k = 2
>>> [[x for i, x in enumerate(a) if i != k] for a in A]
[[1, 2, 4], ['a', 'b', 'd'], [12, 13, 15]]

是的,它里面有for一词(甚至两倍!),但是性能应该与其他任何方法都没有不同(尽管numpy可能更快)。

答案 4 :(得分:1)

您可以轻松使用list comprehensionslices

A = [[1,2,3,4],['a','b','c','d'] , [12,13,14,15]]
k = 1

B = [l[:k]+l[k+1:] for l in A]

print(B) # >> returns [[1, 3, 4], ['a', 'c', 'd'], [12, 14, 15]]