我在python中有一个列表列表列表(所有列表的大小都相同),如下所示:
A = [[1,2,3,4],['a','b','c','d'] , [12,13,14,15]]
我想删除一些列(所有列表的第 i 个元素)。
有什么方法可以在没有for
语句的情况下做到这一点吗?
如前所述,没有循环就无法做到这一点。但是,使用内置函数,这是一种不显式使用任何循环的功能方法:
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]]
请注意,如果您只返回 map(itg, arr)
,则不会list(map(list, 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)
我认为如果您精通zip
,您可以在不for
的情况下做到这一点(这是我最喜欢的"黑客"):
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)))
结果 (i = 2):
[[1, 2, 4], ['a', 'b', 'd'], [12, 13, 15]]
当然,map
是列表理解的另一种选择:
B = list(map(lambda l: l[:i] + l[i + 1:], A))
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']]
另一个使用列表理解的变体,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
可能更快)。
您可以轻松使用列表理解和切片:
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]]