刀剑神域 UW 终章演的什么玩意,都给我看乐了,还不如回去再看一遍加速世界。
MATLAB 逻辑数组索引还是非常好用的,MATLAB 中,索引数组常用的有两种方法,一种是线性索引(linear indices),一种是下标索引(subscripts)。对于逻辑数组,我们同样可以使用这两种索引方法。
首先,我们来观察一下逻辑数组的线性索引到底索引了一些什么东西。
随便构造一个用来索引的矩阵 a,并构造一个简单的逻辑数组 l:
>> a = reshape(1:25,5,5)
a =
1 6 11 16 21
2 7 12 17 22
3 8 13 18 23
4 9 14 19 24
5 10 15 20 25
>> l = logical([1 0 0 1 1])
l =
1×5 logical 数组
1 0 0 1 1
这个时候使用下标索引,即指定a的行和列,可以发现,结果保留了 a 对应 l 为真的行和列:
>> a(l,l)
ans =
1 16 21
4 19 24
5 20 25
如果使用线性索引,结果就比较有趣了:(如果你没听说过线性索引:线性索引一样是按照下标来的,沿着列来数,每一个元素对应一个唯一的编号,比如第一行第一列是 1,第二行第一列是 2……第一列数完了接着数下一列,这样可以按元素提取矩阵中的值,而不像下标索引只能提取出一个子矩阵)
>> a(l)
ans =
1 4 5
>> a([l l])
ans =
1 4 5 6 9 10
可以看出,不论 l 的长度为多少,l 都会索引到 a 中 l 对应位置为真的量,同时,l 索引到的结果,其大小与 l 的大小一致……真的是这样吗?
我们来对比一下利用逻辑值线性索引和利用数值线性索引的区别:
>> a([1 2 3;4 5 6])
ans =
1 2 3
4 5 6
>> [l;l]
ans =
2×5 logical 数组
1 0 0 1 1
1 0 0 1 1
>> a([l;l])
ans =
1
2
7
8
9
10
可以看出,如果利用数值进行线性索引,那么索引到的结果大小会与索引项一致,但是,如果利用逻辑值索引,而且逻辑值的两个维度都大于 1,那么 MATLAB 会自动将逻辑值数组转换成一个列向量,再进行索引。比如 [l;l] 就是一个 2X5 的逻辑数组,如果将其转换成一个列向量(记住 MATLAB 中沿着列是第一个维度),那么其第1,2,7,8,9,10为真,其索引到了 a 的对应为真的项。
如果再考虑特殊一些的情况,逻辑数组的尺寸比被索引矩阵的尺寸大:
>> b = [a>20 false(5,1)]
b =
5×6 logical 数组
0 0 0 0 1 0
0 0 0 0 1 0
0 0 0 0 1 0
0 0 0 0 1 0
0 0 0 0 1 0
此时 b 的尺寸已经比 a 大了,但是仍然可以利用逻辑索引:
>> a(b)
ans =
21
22
23
24
25
因为 b 中为真的值的范围并没有超越 a 的大小,b 中的第 26 至第 30 个值都为假,不会索引到 a 的界限外。
逻辑索引也是索引,所以可以利用这个来赋值,现在来做两个小题目:
一、将 a 中的质数乘 2:
>> a(isprime(a)) = a(isprime(a)) * 2
a =
1 6 22 16 21
4 14 12 34 22
6 8 26 18 46
4 9 14 38 24
10 10 15 20 25
二、将 a 中的质数反向排列:
>> a(isprime(a)) = flip(a(isprime(a)))
a =
1 6 11 16 21
23 13 12 5 22
19 8 7 18 2
4 9 14 3 24
17 10 15 20 25
善用逻辑数组可以省掉很多循环+判断,以及可能存在的矩阵多次变更大小,就是那种一个循环,判断为真了就在原来的矩阵下面加一行的那种代码,这个会反复申请内存,一旦数据量比较大,就会慢,当然其实也不会慢多少,只是 MATLAB 会给一个黄色的警示,看着怪难受的……