Spec-Zone.ru › Octave 6

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, …), потому что оно избегает ненужной операции умножения. Кроме того, умножение может быть не определено для объекта, который нужно дублировать, в то время как индексирование массива всегда определено. Следующий код демонстрирует, как создать 2x3 ячейковый массив из базового элемента, который сам по себе не является скаляром.

{"Hello"}(ones (2, 3))

Следует отметить, что ones (1, n) (строка-вектор единиц) приводит к объекту диапазона (с нулевым приращением). Диапазон хранится внутри как начальное значение, приращение, конечное значение и общее количество значений; поэтому он более эффективен для хранения, чем вектор или матрица единиц, когда количество элементов больше 4. В частности, когда ‘r’ является строкой-вектором, выражения

r(ones (1, n), :)
r(ones (n, 1), :)

дадут одинаковые результаты, но первое будет значительно быстрее, по крайней мере, для ‘r’ и ‘n’ достаточно больших. В первом случае индекс хранится в сжатой форме как диапазон, что позволяет Octave выбрать более эффективный алгоритм обработки выражения.

Общие рекомендации для пользователей, незнакомых с этими техниками, заключаются в использовании функции repmat для дублирования более мелких массивов в более крупные, которая использует такие приемы.

Второе применение индексирования — ускорение кода. Индексирование — быстрая операция, и разумное её использование может сократить потребность в циклах перебора отдельных элементов массива, что является медленной операцией.

Рассмотрим следующий пример, который создает строку-вектор из 10 элементов a, содержащий значения 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

См. также: ind2sub, size.

: [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

См. также: sub2ind, size.

: 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/v6.4.0/Advanced-Indexing.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API