Мы используем различные формы индексирования в Matlab:
На первый взгляд может показаться, что эти формы являются исключительными: индекс является либо стандартным, либо логическим, либо линейным. Однако иногда появляется смесь между несколькими из этих форм. Например,
>> A = magic(3)
A =
8 1 6
3 5 7
4 9 2
>> A(A>5)
ans =
8
9
6
7
Это логическое индексирование, правильно? Но он также имеет некоторые особенности линейной индексации, потому что возвращается вектор столбца. Фактически, логический индекс A>5
имеет тот же эффект, что и линейный индекс find(A>5)
.
В качестве второго примера рассмотрим
>> A = magic(3)
A =
8 1 6
3 5 7
4 9 2
>> A(1:2, [true false true])
ans =
8 6
3 7
В этом выражении для первой координаты используется стандартная (целочисленная) индексация, а для второй используется логическая индексация.
Эти примеры (и более сложные, которые возникают на практике) задают следующие вопросы:
В дальнейшем я использую терминологию, которая, я думаю, более или менее соответствует стандартной практике Matlab. Однако в некоторых случаях мне приходилось сортировать имя, потому что я не знал о существующем. Пожалуйста, дайте мне знать, если есть более стандартные имена, чем те, которые я использую.
Этот ответ пытается прояснить различные типы индексирования и как их можно комбинировать. Другой вопрос заключается в том, как форма (size
) выходного массива определяется как функция формы индексных переменных. Хорошей почтой на этом является Суть индексации Лорен Шуре.
В приведенном описании основное внимание уделяется индексированию числовых массивов, но оно может быть применено к массивам ячеек с индексом скобок или фигурной скобки с очевидным изменением типа вывода (соответственно массива ячеек или списка разделенных запятыми). Это будет кратко обсуждено в конце.
Индексация может быть классифицирована с учетом следующих двух атрибутов.
Согласно числу измерений, к которым относится каждая индексная переменная, индексирование может быть многомерным или линейным. Но это всего лишь два крайних случая. Существует промежуточная ситуация, которую можно назвать частично линейной индексацией:
sub2ind
).m+n
измерениями, n>=2
, можно указать m
индексных переменных для первых m
измерений (таким образом, используя многомерную индексацию в этих измерениях) и одну индексную переменную для последних n
измерений, которая равна интерпретируется как линейный индекс только для этих измерений (последние n
измерений сворачиваются в один).В соответствии с типом значений индекса каждая индексная переменная может быть целочисленной или логической:
Критерии классификации 1 и 2 являются независимыми. Категория индекса с точки зрения критерия 1 не имеет отношения к его категории в соответствии с критерием 2. Возможны все комбинации.
Таким образом, согласно вышеуказанной классификации, существует 6 основных типов индексирования. Чтобы прояснить, ниже приведен пример для каждого. Все примеры используют массив A = cat(3, magic(3), 9+magic(3))
, то есть,
A(:,:,1) =
8 1 6
3 5 7
4 9 2
A(:,:,2) =
17 10 15
12 14 16
13 18 11
Многомерный, целочисленный:
>> A([1 2], 2, 2)
ans =
10
14
Линейный, целочисленный:
>> A([2 5:7])
ans =
3 5 9 6
Частично линейный, целочисленный:
>> A([1 2], 2:4)
ans =
1 6 17
5 7 12
Многомерный, логический:
>> A([true true false], [false true false], [false true])
ans =
10
14
Интересно, что количество логических значений может быть меньше или даже больше, чем размер в измерении, на который ссылается индекс:
>> A([true true], [false true false false], [false true])
ans =
10
14
Недопустимые значения интерпретируются как false
, а избыточные значения должны быть false
или произойдет ошибка. См., Например, эту страницу по Mathworks или этот ответ Джонаса.
Линейный, логический:
>> A([false true false false true true true])
ans =
3 5 9 6
(Обратите внимание, что в векторе индексирования осталось 11 false
значений).
Частично линейный, логический:
>> A([true true false], [false true true true false false])
ans =
1 6 17
5 7 12
При многомерном или частично линейном индексировании, в котором имеется более одной индексной переменной, каждая из них может независимо быть целочисленной или логической. Это приводит к разным смешанным типам. Например:
Многомерный, логический/целочисленный:
>> A([true false true], [false true true], 2)
ans =
10 15
18 11
Частично линейный, целочисленный/логический:
>> A([1 2], [true false true false true false])
ans =
8 6 10
3 7 14
Если массив, который индексируется, является разреженной матрицей, все вышеприведенное все еще применяется, за исключением того, что для матриц не существует частично линейного индексации; и, конечно, результат также разрежен.
Все типы индексирования, описанные для числовых массивов, могут быть применены к массивам ячеек с одним дополнительным рассмотрением. Ячейки могут быть проиндексированы скобками или фигурными фигурными скобками. В первом случае результатом индексации является массив ячеек. Во втором - список содержимого ячейки, разделенный запятыми.
В качестве примера предположим, что численный массив, используемый в предыдущих примерах, преобразуется в массив ячеек C = num2cell(A)
, то есть,
C(:,:,1) =
[8] [1] [6]
[3] [5] [7]
[4] [9] [2]
C(:,:,2) =
[17] [10] [15]
[12] [14] [16]
[13] [18] [11]
Тогда индексирование, используемое в примере 8 выше, даст массив ячеек
>> C([1 2], [true false true false true false])
ans =
[8] [6] [10]
[3] [7] [14]
тогда как использование фигурных скобок даст список, разделенный запятыми
>> C{[1 2], [true false true false true false]}
ans =
8
ans =
3
ans =
6
ans =
7
ans =
10
ans =
14
Логическое и линейное индексирование не являются исключительными типами индексирования. Скорее, это две независимые функции индексирования. "Логический" относится к типу значений индекса, а "linear" означает, что несколько измерений свертываются и индексируются как единое целое. Обе функции могут выполняться одновременно.