假设我有一个矩阵:
[[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
答案 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
将整数转换为真/假值,后续int
将False
转换为0
,或True
至1
。
<强>性能强>
首先,设置 -
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;的最有效的实施。