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

从Python 2D列表中删除列的最佳/快速方法,python,python-3.x,list,filter,Python,Python 3.x,List,Filter,我在python中有一个列表列表(所有列表的大小都相同),如下所示: A = [[1,2,3,4],['a','b','c','d'] , [12,13,14,15]] 我想删除一些列(所有列表的第I个元素) 有没有任何方法可以在不使用的情况下对语句执行此操作?您可以轻松使用并: 如果你精通zip(这是我最喜欢的“hack”),我想你可以不用for就可以做到这一点: 结果(i=2): 当然,map是列表理解的替代方法: B = list(map(lambda l: l[:i] + l[i +

我在python中有一个列表列表(所有列表的大小都相同),如下所示:

A = [[1,2,3,4],['a','b','c','d'] , [12,13,14,15]]
我想删除一些列(所有列表的第I个元素)

有没有任何方法可以在不使用
的情况下对
语句执行此操作?

您可以轻松使用并:


如果你精通
zip
(这是我最喜欢的“hack”),我想你可以不用
for
就可以做到这一点:

结果(i=2):


当然,
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
):


如前所述,如果没有循环,则无法完成此操作。但是,使用内置函数这里有一种不显式使用任何循环的函数方法:

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)))
    ...: 
演示:

请注意,如果您只返回
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)

另一个使用列表理解的变体,带有
枚举

>>> 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]]

是的,这里面有
这个词(两倍偶数!),但是性能不应该与其他任何方法不同(
numpy
可能更快)。

使用numpy是的。否则,您至少需要1个
for
为什么要在没有for语句的情况下执行此操作?当然,您可以用while循环替换for循环,但这只会降低代码的可读性,从根本上说,即使numpy使用循环实现。虽然为了学究式,我们可以使用
,而这里的
循环仍然有一个
用于
,也许你可以包括map?列表理解并不比映射慢,而且它们更具可读性。。。我认为asker想避免使用
for
循环,而不是任何O(1)循环…@olinox14我同意“no for loops”的要求是毫无意义的,因为所有其他方法都有隐藏在其中的循环,但什么是“O(1)循环”?这是衡量算法复杂性的标准方法,看一看,或者我很确定,由于创建了所有临时对象,与标准压缩相比,性能会受到影响。但我可能错了。和
map(lambda
不是recommended@Jean-Françoisfafre肯定你是对的,但是
zip
map
对象应该与生成器(但不是列表理解)相比较。我非常喜欢你的“使用循环”方法……几乎像是某种东西。:-PHm,没想到。虽然,当我测试它时,差异并没有那么显著。而且,我认为迭代器创建的时间有点傻,你不能真正比较它们。@tobias_k当然,它只是作为前面解释的一个教授。关于差异,它不是那么戏剧化这里也是c,不要惊讶,因为这是c的力量和定律。
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]]
In [31]: def remove_col(arr, ith):
    ...:     return [[j for i,j in enumerate(sub) if i != ith] for sub in arr]
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)
>>> 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]]