Ячейки cell и структуры struct

Что делать, когда данные не однородные числа: ячейки для смеси типов и структуры для именованных полей.

Cell-массив хранит значения разных типов и размеров в ячейках; struct группирует данные по именованным полям.

Зачем нужны не-матрицы

Обычная матрица требует, чтобы все элементы были числами одного типа. Но реальные данные бывают разнородными: список имён разной длины, запись о студенте (имя, возраст, оценки). Для этого есть две структуры. Cell-массив задают фигурными скобками {} и индексируют тоже фигурными — каждая ячейка может содержать что угодно.

c = {'Ada', 42, [1 2 3]};   % строка, число, вектор
c{1}              % 'Ada' — содержимое первой ячейки
c{3}              % [1 2 3]

Обратите внимание: c{1} в фигурных скобках достаёт содержимое ячейки, а c(1) в круглых вернул бы ячейку как контейнер. Это ключевое различие.

Структуры с полями

Структура хранит данные под осмысленными именами полей через точку. Это как запись или объект без методов. Поля создают присваиванием.

student.name = 'Ada';
student.age = 20;
student.grades = [5 4 5];
student.name           % 'Ada'
mean(student.grades)   % 4.6667

Вывод:

ans =
    'Ada'

ans =
    4.6667

Массивы структур

Структуры можно собирать в массивы — получится таблица записей с одинаковыми полями. students(1).name, students(2).name и так далее. Это удобно для наборов однотипных объектов; для табличных данных, впрочем, чаще берут тип table (он будет в разделе про данные).

Параллель с Python

Cell-массив похож на список Python, способный держать разные типы. Структура напоминает словарь с фиксированными ключами или именованный кортеж. Разница в том, что поля структуры — это идентификаторы (доступ через точку), а не произвольные строковые ключи; для произвольных ключей в MATLAB есть отдельный тип containers.Map или dictionary.

Как работает под капотом

Cell-массив хранит не сами значения, а указатели на них — поэтому ячейки могут быть любого размера. Это объясняет, почему индексация двух видов: круглые скобки работают с самим cell-контейнером (можно взять подмассив ячеек), фигурные — разыменовывают, доставая содержимое. Структуры же хранят поля как отдельные переменные, сгруппированные под общим именем; массив структур держит все одноимённые поля согласованными по форме.

Контейнеры с произвольными ключами

Поля структуры — это идентификаторы, известные на этапе написания кода. Но иногда ключи становятся известны только во время выполнения или должны быть произвольными строками либо числами — например, словарь «город → население». Для таких случаев MATLAB предлагает containers.Map, а в новых версиях — тип dictionary: они хранят пары «ключ — значение» и позволяют добавлять записи динамически. Это прямой аналог словаря Python. Выбор между структурой и словарём прост: если набор полей фиксирован и известен заранее — структура (доступ через точку нагляднее), если ключи произвольны и меняются во время работы — словарь. Понимание этой границы избавляет от попыток втиснуть динамические ключи в структуру, что приводит к неуклюжему коду с dynamic field names.

Частые ошибки

  • Путать c(1) (ячейка-контейнер) и c{1} (содержимое) — самый частый промах с cell.
  • Пытаться сложить разнородный cell как матрицу — нужно сначала извлечь числа.
  • Обращаться к несуществующему полю структуры — ошибка; проверяйте через isfield.

Когда выбирать cell, struct или table

Три структуры для разнородных данных решают разные задачи, и важно выбирать осознанно. Cell-массив хорош, когда элементы разнотипны и доступ к ним идёт по позиции (первый, второй, третий) — например, список заголовков разной длины. Struct уместна, когда у сущности есть осмысленные именованные характеристики (имя, возраст, оценки) и обращаться к ним удобнее по имени, а не по номеру. Table (из раздела про данные) — для табличных данных, где много однотипных записей с одинаковыми полями-столбцами. Грубое правило: позиция — cell, именованные поля одного объекта — struct, таблица записей — table.

Массивы структур и поля-векторы

У массива структур есть приятная особенность: к одноимённому полю всех элементов можно обратиться разом через [students.age] — квадратные скобки соберут возрасты всех студентов в один числовой вектор, к которому уже применимы mean, max и прочая статистика. Это мост между «объектным» представлением (массив записей) и «матричным» (вектор значений одного поля). Однако злоупотреблять глубокими вложенными структурами не стоит: когда данные становятся по-настоящему табличными, table читается и обрабатывается куда удобнее, чем массив структур с ручной сборкой полей.

Итоги

  • Cell-массив {} хранит разнородные значения; {} достаёт содержимое, () — ячейку.
  • Struct группирует данные по именованным полям через точку.
  • Массивы структур — наборы однотипных записей; для таблиц лучше table.
Проверьте себя
1. Чем cell-массив отличается от обычной матрицы?
AНичем
BCell может хранить значения разных типов и размеров
CCell быстрее
DCell только для чисел
2. Чем отличается c{1} от c(1) для cell-массива?
AНичем
Bc{1} даёт содержимое ячейки, c(1) — саму ячейку-контейнер
Cc(1) вызывает ошибку
Dc{1} только для чисел
3. Как обращаются к полю структуры student?
Astudent->name
Bstudent.name
Cstudent{name}
Dstudent[name]