索引矩陣和陣列
MATLAB 允許多種方法來索引(訪問)矩陣和陣列的元素:
- 下標索引 - 你可以分別在矩陣的每個維度中指定所需元素的位置。
- 線性索引 - 矩陣被視為向量,無論其大小如何。這意味著,你可以使用單個數字指定矩陣中的每個位置。
- 邏輯索引 - 你使用邏輯矩陣(以及
true
和false
值的矩陣),其中你嘗試將矩陣的相同維度作為掩碼進行索引,以指定要返回的值。
現在使用以下 3 乘 3 矩陣 M
作為示例更詳細地解釋這三種方法:
>> M = magic(3)
ans =
8 1 6
3 5 7
4 9 2
下標索引
訪問元素最直接的方法是指定其行列索引。例如,訪問第二行和第三列上的元素:
>> M(2, 3)
ans =
7
提供的下標數量與 M
的維度數量完全匹配(本例中為 2)。
請注意,下標的順序與數學約定相同:行索引是第一個。此外,MATLAB 索引以 1
開頭,而不是像大多數程式語言一樣的 0
。
你可以通過為每個座標傳遞向量而不是單個數字來一次索引多個元素。例如,為了獲得整個第二行,我們可以指定我們想要第一,第二和第三列:
>> M(2, [1,2,3])
ans =
3 5 7
在 MATLAB 中,使用冒號運算子(即 1:3
)更容易建立向量 [1,2,3]
。你也可以在索引中使用它。要選擇整行(或列),MATLAB 允許你只指定:
來提供快捷方式。例如,以下程式碼也將返回整個第二行
>> M(2, :)
ans =
3 5 7
MATLAB 還提供了一個快捷方式,用於以 end
關鍵字的形式指定維度的最後一個元素。end
關鍵字的工作方式與該維度中最後一個元素的編號完全相同。因此,如果你希望列 2
中的所有列到最後一列,你可以使用以下內容編寫:
>> M(2, 2:end)
ans =
5 7
下標索引可能是限制性的,因為它不允許從不同的列和行中提取單個值; 它將提取所有行和列的組合。
>> M([2,3], [1,3])
ans =
3 7
4 2
例如,下標索引不能僅提取元素 M(2,1)
或 M(3,3)
。為此,我們必須考慮線性索引。
線性索引
當你僅使用一個維度進行索引時,MATLAB 允許你將 n 維陣列視為一維陣列。你可以直接訪問第一個元素:
>> M(1)
ans =
8
請注意,陣列在 MATLAB 中以列主順序儲存,這意味著你可以通過首先向下列來訪問元素。所以 M(2)
是第一列的第二個元素,即 3
,M(4)
將是第二列的第一個元素,即
>> M(4)
ans =
1
在 MATLAB 中存在內建函式將下標索引轉換為線性索引,反之亦然: sub2ind
和 ind2sub
。你可以手動將下標(r
,c
)轉換為線性索引
idx = r + (c-1)*size(M,1)
要理解這一點,如果我們在第一列,那麼線性索引將只是行索引。上面的公式適用於此,因為對於 c == 1
,(c-1) == 0
。在下一列中,線性索引是行號加上前一列的所有行。
請注意,end
關鍵字仍然適用,現在引用陣列的最後一個元素即 M(end) == M(end, end) == 2
。
你還可以使用線性索引來索引多個元素。請注意,如果這樣做,返回的矩陣將具有與索引向量矩陣相同的形狀。
M(2:4)
返回一個行向量,因為 2:4
代表行向量 [2,3,4]
:
>> M(2:4)
ans =
3 4 1
作為另一個例子,M([1,2;3,4])
返回 2 乘 2 的矩陣,因為 [1,2;3,4]
也是 2 乘 2 的矩陣。請參閱以下程式碼以說服自己:
>> M([1,2;3,4])
ans =
8 3
4 1
請注意,僅使用:
索引將始終返回列向量:
>> M(:)
ans =
8
3
4
1
5
9
6
7
2
此示例還說明了 MATLAB 在使用線性索引時返回元素的順序。
邏輯索引
第三種索引方法是使用邏輯矩陣,即僅包含 true
或 false
值的矩陣作為掩碼來過濾掉你不想要的元素。例如,如果我們想要找到 M
的所有元素大於 5
,我們可以使用邏輯矩陣
>> M > 5
ans =
1 0 1
0 0 1
0 1 0
索引 M
並僅返回大於 5
的值,如下所示:
>> M(M > 5)
ans =
8
9
6
7
如果你想讓這些數字保持原位(即保持矩陣的形狀),那麼你可以分配給邏輯恭維
>> M(~(M > 5)) = NaN
ans =
8 NaN 6
NaN NaN 7
NaN 9 Nan
我們可以通過使用邏輯索引來減少包含 if
和 for
語句的複雜程式碼塊。
採用非向量化(通過使用線性索引已經縮短為單個迴圈):
for elem = 1:numel(M)
if M(elem) > 5
M(elem) = M(elem) - 2;
end
end
這可以使用邏輯索引縮短為以下程式碼:
idx = M > 5;
M(idx) = M(idx) - 2;
甚至更短:
M(M > 5) = M(M > 5) - 2;
更多關於索引
更高維矩陣
上面提到的所有方法都歸納為 n 維。如果我們使用三維矩陣 M3 = rand(3,3,3)
作為示例,那麼你可以通過寫入訪問第三維的第二個切片的所有行和列
>> M(:,:,2)
你可以使用線性索引訪問第二個切片的第一個元素。線性索引僅在第一個切片的所有行和所有列之後移動到第二個切片。所以該元素的線性索引是
>> M(size(M,1)*size(M,2)+1)
實際上,在 MATLAB 中,每個矩陣都是 n 維的:恰好是大多數其他 n 維的大小都是 1。那麼,如果 a = 2
那麼 a(1) == 2
(正如人們所期待的那樣),還有 a(1, 1) == 2
,就像 a(1, 1, 1) == 2
,a(1, 1, 1, ..., 1) == 2
等等。這些額外尺寸(尺寸為 1
)被稱為單一尺寸。命令 squeeze
將刪除它們,並且可以使用 permute
來交換維度的順序(並且如果需要則引入單個維度)。
還可以使用 m 個下標(其中 m <= n)來索引 n 維矩陣。規則是第一個 m-1 下標通常表現,而最後一個(第 m 個)下標引用剩餘的(n-m + 1)維度,就像線性索引引用(n-m + 1)維一樣陣列。這是一個例子:
>> M = reshape(1:24,[2,3,4]);
>> M(1,1)
ans =
1
>> M(1,10)
ans =
19
>> M(:,:)
ans =
1 3 5 7 9 11 13 15 17 19 21 23
2 4 6 8 10 12 14 16 18 20 22 24
返回元素範圍
使用下標索引,如果在多個維度中指定多個元素,MATLAB 將返回每對可能的座標。例如,如果你嘗試 M([1,2],[1,3]),MATLAB 將返回 M(1,1)
和 M(2,3)
,但它也將返回 M(1,3)
和 M(2,1)
。當你查詢座標對列表的元素時,這似乎不直觀,但考慮更大矩陣的示例,A = rand(20)
(注意 A
現在是 20
-by-20
),你想要獲得右上象限。在這種情況下,不必指定該象限中的每個座標對(這種情況下將是 100
對),你只需指定 10
行和 10
列即可。切片像這樣的矩陣比需要座標對列表更常見。
如果你確實想要獲得座標對列表,最簡單的解決方案是轉換為線性索引。考慮一個問題,其中有一個要返回的列索引向量,其中向量的每一行包含要為矩陣的相應行返回的列號。例如
colIdx = [3;2;1]
所以在這種情況下你真的想要回到 (1,3)
,(2,2)
和 (3,1)
的元素。所以使用線性索引:
>> colIdx = [3;2;1];
>> rowIdx = 1:length(colIdx);
>> idx = sub2ind(size(M), rowIdx, colIdx);
>> M(idx)
ans =
6 5 4
多次返回元素
使用下標和線性索引,你還可以通過重複索引來多次返回元素
>> M([1,1,1,2,2,2])
ans =
8 8 8 3 3 3
你可以使用它來複制整個行和列,例如重複第一行和最後一列
>> M([1, 1:end], [1:end, end])
ans =
8 1 6 6
8 1 6 6
3 5 7 7
4 9 2 2
有關更多資訊,請參閱此處 。