8.1.1 Дополнительный индексирование
Когда необходимо извлечь подмножества записей из массива, индексы которых нельзя записать как декартово произведение компонентов, можно использовать линейный индексирование вместе с функцией sub2ind. Например:
A = reshape (1:8, 2, 2, 2) # Create 3-D array A = ans(:,:,1) = 1 3 2 4 ans(:,:,2) = 5 7 6 8 A(sub2ind (size (A), [1, 2, 1], [1, 1, 2], [1, 2, 1])) ⇒ ans = [A(1, 1, 1), A(2, 1, 2), A(1, 2, 1)]
Массив с ‘nd’ измерениями может быть индексирован выражением индекса, имеющим от 1 до ‘nd’ компонентов. В обычном и наиболее частом случае количество компонентов ‘M’ совпадает с количеством измерений ‘nd’. В этом случае применяются обычные правила индексирования, и каждый компонент соответствует соответствующему измерению массива.
Однако, если количество компонентов индексирования превышает количество измерений (M > nd) то избыточные компоненты должны быть все одиночными (1). Кроме того, если M < nd, поведение эквивалентно переформированию входного объекта таким образом, чтобы объединить последующие nd - M измерения в последнее индексное измерение M. Таким образом, результат будет иметь размерность выражения индекса, а не исходного объекта. Это имеет место всякий раз, когда размерность индекса больше единицы (M > 1), так что специальные правила для линейного индексирования не применяются. Это легче понять на примере:
A = reshape (1:8, 2, 2, 2) # Create 3-D array A = ans(:,:,1) = 1 3 2 4 ans(:,:,2) = 5 7 6 8 ## 2-D indexing causes third dimension to be merged into second dimension. ## Equivalent array for indexing, Atmp, is now 2x4. Atmp = reshape (A, 2, 4) Atmp = 1 3 5 7 2 4 6 8 A(2,1) # Reshape to 2x4 matrix, second entry of first column: ans = 2 A(2,4) # Reshape to 2x4 matrix, second entry of fourth column: ans = 8 A(:,:) # Reshape to 2x4 matrix, select all rows & columns, ans = Atmp
Обратите внимание на изящное использование двойного двоеточия для замены вызова функции reshape.
Другое расширенное использование линейного индексирования — создание массивов, заполненных одним значением. Это можно сделать, используя индекс из единиц на скалярном значении. Результатом является объект с размерами выражения индекса и всеми элементами, равными исходному скаляру. Например, следующие операторы
a = 13; a(ones (1, 4))
генерируют строку-вектор, чьи четыре элемента все равны 13.
Аналогично, индексируя скаляр двумя векторами из единиц, можно создать матрицу. Следующие операторы
a = 13; a(ones (1, 2), ones (1, 3))
создают матрицу 2x3 со всеми элементами, равными 13. Это также можно было записать как
13(ones (2, 3))
Более эффективно использовать индексирование, а не конструкцию кода scalar * ones (M, N, …), потому что это позволяет избежать ненужной операции умножения. Кроме того, умножение может быть не определено для объекта, подлежащего дублированию, в то время как индексирование массива всегда определено. Следующий код показывает, как создать двумерный массив ячеек из базового блока, который сам по себе не является скаляром.
{"Hello"}(ones (2, 3)) Следует отметить, что ones (1, n) (строка-вектор из единиц) приводит к объекту диапазона (с нулевым приращением). Диапазон хранится в памяти как начальное значение, приращение, конечное значение и общее количество значений; следовательно, он более эффективен для хранения, чем вектор или матрица единиц всякий раз, когда количество элементов больше 4. В частности, когда ‘r’ является строкой-вектором, выражения
r(ones (1, n), :)
r(ones (n, 1), :)
будут давать одинаковые результаты, но первое будет значительно быстрее, по крайней мере, для ‘r’ и ‘n’ достаточно больших. В первом случае индекс хранится в сжатом виде как диапазон, что позволяет Octave выбрать более эффективный алгоритм для обработки выражения.
Общее рекомендация для пользователей, незнакомых с этими техниками, — использовать функцию repmat для копирования меньших массивов в более большие, которая использует такие приемы.
Второе применение индексирования — ускорение кода. Индексирование — быстрая операция, и его продуманное использование может уменьшить необходимость перебора отдельных элементов массива, что является медленной операцией.
Рассмотрим следующий пример, который создает строку-вектор a из 10 элементов, содержащий значения a(i) = sqrt (i).
for i = 1:10 a(i) = sqrt (i); endfor
Создание вектора с помощью цикла таким образом довольно неэффективно. В этом случае гораздо эффективнее использовать выражение
a = sqrt (1:10);
что полностью избегает цикла.
В тех случаях, когда цикл избежать невозможно или нужно объединить ряд значений для формирования большей матрицы, обычно быстрее сначала установить размер матрицы (зарезервировать память), а затем вставлять элементы с помощью команд индексирования. Например, при заданной матрице a,
[nr, nc] = size (a); x = zeros (nr, n * nc); for i = 1:n x(:,(i-1)*nc+1:i*nc) = a; endfor
значительно быстрее, чем
x = a; for i = 1:n-1 x = [x, a]; endfor
потому что Octave не должен многократно изменять размер промежуточного результата.
- : ind = sub2ind (dims, i, j) ¶
- : ind = sub2ind (dims, s1, s2, …, sN) ¶
-
Преобразовать индексы подстрок в линейные индексы.
Входные данные dims — это вектор размерностей, где каждый элемент — размер массива в соответствующем измерении (см.
size). Остальные входные данные — скаляры или векторы индексов, которые необходимо преобразовать.Выходной вектор ind содержит преобразованные линейные индексы.
Предыстория: элементы массива можно указать либо с помощью линейного индекса, который начинается с 1 и проходит через количество элементов в массиве, либо с помощью индексов для строки, столбца, страницы и т. д. Функции
ind2subиsub2indосуществляют взаимопреобразование между двумя формами.Линейный индекс проходит по измерению 1 (строкам), затем по измерению 2 (столбцам), затем по измерению 3 (страницам) и т. д., пока не пронумерует все элементы. Рассмотрим следующие 3×3 матрицы:
[(1,1), (1,2), (1,3)] [1, 4, 7] [(2,1), (2,2), (2,3)] ==> [2, 5, 8] [(3,1), (3,2), (3,3)] [3, 6, 9]
Левая матрица содержит кортежи индексов для каждого элемента матрицы. Правая матрица показывает линейные индексы для той же матрицы.
Следующий пример показывает, как преобразовать двумерные индексы
(2,1)и(2,3)матрицы 3×3 в линейные индексы с помощью единственного вызоваsub2ind.s1 = [2, 2]; s2 = [1, 3]; ind = sub2ind ([3, 3], s1, s2) ⇒ ind = 2 8
- : [s1, s2, …, sN] = ind2sub (dims, ind) ¶
-
Преобразовать линейные индексы в индексы подстрок.
Входные данные dims — это вектор размерностей, где каждый элемент — размер массива в соответствующем измерении (см.
size). Второй входной параметр ind содержит линейные индексы, которые нужно преобразовать.Выходные данные s1, …, sN содержат преобразованные индексы подстрок.
Предыстория: элементы массива можно указать либо с помощью линейного индекса, который начинается с 1 и проходит через количество элементов в массиве, либо с помощью индексов для строки, столбца, страницы и т. д. Функции
ind2subиsub2indосуществляют взаимопреобразование между двумя формами.Линейный индекс проходит по измерению 1 (строкам), затем по измерению 2 (столбцам), затем по измерению 3 (страницам) и т. д., пока не пронумерует все элементы. Рассмотрим следующие 3×3 матрицы:
[1, 4, 7] [(1,1), (1,2), (1,3)] [2, 5, 8] ==> [(2,1), (2,2), (2,3)] [3, 6, 9] [(3,1), (3,2), (3,3)]
Левая матрица содержит линейные индексы для каждого элемента матрицы. Правая матрица показывает кортежи индексов подстрок для той же матрицы.
Следующий пример показывает, как преобразовать двумерные индексы
(2,1)и(2,3)матрицы 3×3 в линейные индексы с помощью единственного вызоваsub2ind.Следующий пример показывает, как преобразовать линейные индексы
2и8в матрице 3×3 в индексы подстрок.ind = [2, 8]; [r, c] = ind2sub ([3, 3], ind) ⇒ r = 2 2 ⇒ c = 1 3Если количество выходных индексов подстрок превышает количество измерений, то избыточные измерения устанавливаются в
1. С другой стороны, если количество индексов подстрок меньше количества измерений, то избыточные измерения объединяются в окончательное требуемое измерение. Для ясности рассмотрим следующие примеры:ind = [2, 8]; dims = [3, 3]; ## same as dims = [3, 3, 1] [r, c, s] = ind2sub (dims, ind) ⇒ r = 2 2 ⇒ c = 1 3 ⇒ s = 1 1 ## same as dims = [9] r = ind2sub (dims, ind) ⇒ r = 2 8
- : isindex (ind) ¶
- : isindex (ind, n) ¶
-
Возвращает true, если ind является допустимым индексом.
Допустимыми индексами являются либо положительные целые числа (возможно, действительного типа данных), либо логические массивы.
Если присутствует n, он задает максимальное значение измерения, подлежащего индексированию. Если это возможно, внутренний результат кэшируется, так что последующее индексирование с помощью ind не будет выполнять проверку снова.
Примечание по реализации: строки сначала преобразуются в значения типа double перед выполнением проверок на корректность индексов. За исключением случая, когда строка содержит нулевой символ «\0», она всегда будет допустимым индексом.
© 1996–2022 The Octave Project Developers
Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.
Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions.
https://docs.octave.org/v7.2.0/Advanced-Indexing.html