MATLAB.Exponenta
–Û·Ë͇ Matlab&Toolboxes

MATLAB

В.Г.Потемкин "Введение в Matlab" (v 5.3)
Глава 6. Массивы записей

  В оглавление книги \ К следующему разделу \ К предыдущему разделу \ Предметный указатель

6.4. Организация данных. Вложенные структуры. Многомерные массивы структур

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

Рассмотрим RGB-изображение размером 128x128 пикселей, записанное в трех массивах: RED, GREEN, BLUE:

ris604.gif (5444 bytes)

Рис. 6.4

Имеются, по крайней мере, два способа организации этих данных в структуру, как это показано на рис. 6.5 а, б.

ris605a.gif (3407 bytes) ris605b.gif (4154 bytes)

                       а)                                                                              б)

Рис. 6.5

Матричная организация. В этом случае каждое поле структуры - это массив координат точек одного цвета. Такую структуру можно создать, используя следующие присваивания

                 A.r = RED;
                 A.g = GREEN;
                 A.b = BLUE;

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

                 red_plane = A.red;

Матричная организация имеет преимущества при работе со множеством изображений, когда эти изображения можно накопить в виде массивов A(2), A(3), ….. , содержащих целые образы.

Недостаток такой организации очевиден, когда требуется получить доступ к подмассиву массива цветов. Для того чтобы получить доступ к подобразу, необходимо получить доступ к определенным участкам поля структуры, например, таким

                 red_sub = A.r(2:12, 13:30);
                 grn_sub = A.g(2:12, 13:30);
                 blue_sub = A.b(2:12, 13:30);

Поэлементная организация. В этом случае определение отдельных элементов данных реализуется в виде циклов

                 for i = 1:size(RED, 1)
                     for j = 1:size(RED, 2)
                         B(i, j).r = RED(i, j);
                         B(i, j).g = GREEN(i, j);
                         B(i, j).b = BLUE(i, j);
                     end
                 end

При такой организации доступ к подмножеству данных может быть выполнен с помощью оператора присваивания

                Bsub = B(1:10,1:10); .

Однако, чтобы получить доступ к матрице, требуется организовать цикл:

                red_plane = zeros(128, 128);
                for i = 1:(128*128)
                   red_plane(i) = B(i).r;
                end

Поэлементная организация - не лучший выбор для приложений, связанных с обработкой изображений; однако он может оказаться предпочтительным, когда необходим доступ к отдельным участкам полей.

Следующий пример демонстрирует преимущества такого подхода.

Пример.
Рассмотрим следующие два варианта организации базы данных (рис.6.6):

ris606a.gif (2769 bytes) ris606b.gif (2763 bytes)

                  а)                                                                      б)

Рис. 6.6

Каждая из них имеет свои преимущества и недостатки:

  • Матричная организация позволяет упростить обработку полей данных.

Пример.
Нахождение среднего всех значений поля amount реализуется следующим образом:
     в случае матричной организации:
              avg = mean(A.amount);
     в случае поэлементной организации:
              avg = mean([B.amount]);

  • Поэлементная организация позволяет упростить доступ к полям, связанным с отдельной записью.

Пример.
Рассмотрим М-файл client.m, который выводит на экран имя и адрес клиента.
           -  в случае матричной организации надо отображать индивидуальные поля:
            function client(name, address)
            disp(name)
            disp(address)
            - в случае поэлементной организации можно отобразить целую запись:
            function client(B)
            disp(B)

Вызов функции client должен быть организован следующим образом:
           - в случае матричной организации:
            client(A.name(2,:),A.address(2,:))
           - в случае поэлементной организации:
            client(B(2))

Поэлементная организация упрощает работу со строками переменной длины. В случае матричной организации, если априори неизвестна максимальная длина строки, придется многократно определять размеры полей name или address, чтобы разместить более длинные строки.

Обычно сами данные не диктуют выбор схемы организации; ее определяют операции доступа и обработки данных.

Вложенные структуры.

Поле структуры может само включать другую структуру или даже массив структур. Как только структура создана, с помощью операторов присваивания или функции struct можно вложить структуры в существующие поля.

Применение функции struct. Чтобы сформировать вложенную структуру, необходимо организовать рекурсию при вызове функции struct.

Пример.
Допустим, что требуется создать структуру размера 1х2. Организуем следующий рекурсивный вызов функции struct:

        A = struct('data',[3 4 7; 8 0 1],'nest',...
            struct('testnum','Test 1','xdata',[4 2 8],'ydata',[7 1 6]))

         A =
            data: [2x3 double]
            nest: [1x1 struct]

Запись A(1) содержит требуемые значения, благодаря вызову внешней функции struct.

Следующая последовательность операторов производит результат, аналогичный предыдущему:

         A(1).data = [3 4 7; 8 0 1];
         A(1).nest.testnum = 'Test 1';
         A(1).nest.xdata = [4 2 8];
         A(1).nest.ydata = [7 1 6];
         A(2).data = [9 3 2; 7 6 5];
         A(2).nest.testnum = 'Test 2';
         A(2).nest.xdata = [3 4 2];
         A(2).nest.ydata = [5 0 9]
         A =
             1x2 struct array with fields:
                 data
                 nest

Введем изменения в запись A(2):

         A(2).data = [9 3 2; 7 6 5];
         A(2).nest.testnum = 'Test 2';
         A(2).nest.xdata = [3 4 2];
         A(2).nest.ydata = [5 0 9]

         A =
              1x2 struct array with fields:
                  data
                  nest

Тогда получим следующую структуру:

ris607.gif (3677 bytes)

Рис. 6.7

Как и в случае массивов записей с одним уровнем вложения, можно с использованием операторов присваивания сформировать вложенные массивы структур.

Индексация вложенных структур. Для того чтобы проиндексировать структуру, надо добавить имена вложенных полей, используя в качестве разделителя точку (.). Первая текстовая строка индексного выражения определяет имя структуры, а последующие имена полей, содержащих другие структуры.

Пример.
Вышеописанный массив A имеет 2 уровня вложенности:

  • для получения доступа к вложенной структуре внутри A(1) надо использовать A(1).nest.
  • для получения доступа к полю xdata вложенной структуры внутри A(1) надо использовать A(2).nest.xdata.
  • для получения доступа к элементу 2 поля ydata вложенной структуры внутри A(1) надо использовать A(1).nest.ydata(2).

Многомерные массивы структур.

Многомерные массивы структур рассматриваются как расширение прямоугольных массивов структур. По аналогии с другими типами многомерных массивов их можно формировать, либо используя операторы присваивания, либо функцию cat.

Пример.
Сформируем многомерный массив структур следующего вида, используя операторы присваивания (рис. 6.8):

       patient(1, 1, 1).name = 'John Doe';patient(1,1,1).billing = 127.00;
       patient(1, 1, 1).test = [79 75 73; 180 178 177.5; 220 210 205];
       patient(1, 2, 1).name = 'Ann Lane';patient(1,2,1).billing = 28.50;
       patient(1, 2, 1).test = [68 70 68; 118 118 119; 172 170 169];
       patient(1, 1, 2).name = 'Al Smith';patient(1,1,2).billing = 504.70;
       patient(1, 1, 2).test = [80 80 80; 153 153 154; 181 190 182];
       patient(1, 2, 2).name = 'Dora Jones';patient(1,2,2).billing =1173.90;
       patient(1, 2, 2).test = [73 73 75; 103 103 102; 201 198 200];

ris608a.gif (3430 bytes)

ris608b.gif (3371 bytes)

Рис. 6.8. Многомерный массив структур размера 1х2х2.

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

Пример.
Вычислить сумму значений столбцов массива test для структуры patient(1, 1, 2):

            sum((patient(1, 1, 2).test))
            ans =       414    423    416

Суммировать все поля billing 3-мерного массива структур patient:

            total = sum([patient.billing])
            total =       1834.10

  В оглавление книги \ К следующему разделу \ К предыдущему разделу \ Предметный указатель

 


Поиск по сайту:

Система Orphus

Яндекс.Метрика