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

Pan*_*tch 1 python list nested-lists

假设我有一个矩阵:

[[1, 1, 1, 0, 0,], [0, 1, 0, 1], [1, 0, 1]]
Run Code Online (Sandbox Code Playgroud)

我希望它改为:

[[0, 0, 0, 1, 1,], [1, 0, 1, 0], [0, 1, 0]]
Run Code Online (Sandbox Code Playgroud)

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

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

for my_row in my_mat:
   for my_val in my_row:
      my_val = 1 if my_val == 0 else 0
Run Code Online (Sandbox Code Playgroud)

cs9*_*s95 10

我不认为它很慢,但它不是最快的.以下是一些更快的替代方案.

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

>>> [[1 - j for j in i] for i in lst]
[[0, 0, 0, 1, 1], [1, 0, 1, 0], [0, 1, 0]]
Run Code Online (Sandbox Code Playgroud)

这消除了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]]
Run Code Online (Sandbox Code Playgroud)

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]]
Run Code Online (Sandbox Code Playgroud)

请注意,此南瓜为1.非零值not的整数转换为真理/ falsey值,以及随后int转换False0,或True1.


性能

一,设置 -

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

%timeit [[int(not j) for j in i] for i in lst]
%timeit [[j ^ 1 for j in i] for i in lst]
%timeit [[1 - j for j in i] for i in lst]

10 loops, best of 3: 175 ms per loop
10 loops, best of 3: 89.8 ms per loop
10 loops, best of 3: 61.1 ms per loop
Run Code Online (Sandbox Code Playgroud)

接下来,if表现 -

>>> [[1 - j for j in i] for i in lst]
[[0, 0, 0, 1, 1], [1, 0, 1, 0], [0, 1, 0]]
Run Code Online (Sandbox Code Playgroud)

>>> [[j ^ 1 for j in i] for i in lst]
[[0, 0, 0, 1, 1], [1, 0, 1, 0], [0, 1, 0]]
Run Code Online (Sandbox Code Playgroud)

>>> [[int(not j) for j in i] for i in lst]
[[0, 0, 0, 1, 1], [1, 0, 1, 0], [0, 1, 0]]
Run Code Online (Sandbox Code Playgroud)

  • 嘿,这很可爱. (3认同)
  • 也许`j ^ 1`是另一种选择? (2认同)

AnT*_*AnT 7

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

但是如果你在物理上需要反转矩阵中的每个值,那么只有一个"算法" - 你已经发现的那个.其余的不是"算法",而是关于"算法"的最有效实施.