在2D列表中交换0和1的最快方式

时间:2018-01-19 23:59:20

标签: python list nested-lists

假设我有一个矩阵:

[[1, 1, 1, 0, 0,], [0, 1, 0, 1], [1, 0, 1]]

我希望它改为:

[[0, 0, 0, 1, 1,], [1, 0, 1, 0], [0, 1, 0]]

什么可能是处理这种情况的最快方法?

目前,我在另一个 for循环中使用 for loop ,如下所示,这显然太慢了。

for my_row in my_mat:
   for my_val in my_row:
      my_val = 1 if my_val == 0 else 0

2 个答案:

答案 0 :(得分:10)

我觉得它很慢,但它并不是最快的。以下是一些更快的替代方案。

选项1
只需从列表推导中的每个值中减去一个。

>>> [[1 - j for j in i] for i in lst]
[[0, 0, 0, 1, 1], [1, 0, 1, 0], [0, 1, 0]]

这消除了if检查的需要。虽然,只有你有一个0/1的列表才有意义,你只想翻转这些值。

列表推导的好处在于它们能够比循环更快地执行,因为它们已经过优化。

选项2
@trincot建议的另一个替代方法是使用1进行XOR运算。

>>> [[j ^ 1 for j in i] for i in lst]
[[0, 0, 0, 1, 1], [1, 0, 1, 0], [0, 1, 0]]

XOR操作一般来说很快,所以如果你的值超过1,那么这是一个很好的选择。

选项3
@DYZ建议的第三个选项使用not来反转这些值 -

>>> [[int(not j) for j in i] for i in lst]
[[0, 0, 0, 1, 1], [1, 0, 1, 0], [0, 1, 0]]

请注意,这会将非零值压缩为1. not将整数转换为真/假值,后续intFalse转换为0 ,或True1

<强>性能

首先,设置 -

lst = np.random.choice(2, (1000, 1000)).tolist()

接下来,timeit表现 -

# DYZ's suggestion with `not`

%timeit [[int(not j) for j in i] for i in lst]
10 loops, best of 3: 175 ms per loop

# trincot's suggestion with XOR `^`

%timeit [[j ^ 1 for j in i] for i in lst]
10 loops, best of 3: 89.8 ms per loop

# original solution

%timeit [[1 - j for j in i] for i in lst]
10 loops, best of 3: 61.1 ms per loop

答案 1 :(得分:7)

最快&#34;算法&#34;会让你的矩阵不受影响。请记住,在一个单独的标志中,您读取(或写入)的每个值都必须被反转。完成。

但是如果你实际上需要反转矩阵中的每个值,那么只有一个&#34; algo&#34;为此 - 你已经发现的那个。其余的不是&#34; algo&#34;,它是关于&#34; algo&#34;的最有效的实施