Arhlit - информационные технологии

Как сохранить эту структуру (список списков целых чисел) в Matlab?

Мне нужно сохранить список списков целых чисел. Например, X[1] может содержать [1 3 5], а X[2] может содержать [1 2]. Какое лучшее решение? Массив ячеек?


Предыстория:

Для проекта я предварительно рассчитываю пересечения между N линиями и M кубами. Они извлекаются двумя способами: при наличии индекса строки мне нужен список кубов, через которые он проходит, и при заданном индексе куба мне нужен список строк, которые через него проходят.

Типичные значения: N=2^24 и M=2^18, что означает, что о матрице пересечения (NxM) не может быть и речи. К счастью, средняя линия проходит только через M^(1/3)=2^6 кубов. В настоящее время я сохраняю структуру в виде матрицы NxM^(1/3), так что X(n,:) — это вектор кубов, через которые проходит n-я строка (дополненная нулями).

Это прекрасно работает для извлечения кубов с заданным индексом списка, но оказалось, что узким местом моего кода является извлечение строк с заданным индексом куба. (Я делаю это с find(X==m), где m — индекс куба.) Я не могу создать противоположную матрицу, так как количество строк, проходящих через один куб, может быть очень большим, хотя в среднем оно мало.

07.12.2012

Ответы:


1

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

%Writes
X = {[1], [1 2 3], [1 2]};
X{4} = [1 2 3 4];

%Reads
a = X{1}
b = cat(2,X{:});
c = X([2 4]);

Однако это не единственный ответ.

Вы можете использовать массив структур, каждая из которых имеет поле с именем .indexes (или подходящее имя в зависимости от вашей проблемы). Это дает немного больше гибкости, если есть дополнительная информация, которую вы хотели бы прикрепить к вашему списку списков, например, позиция куба может быть добавлена ​​как поле .position. Пример использования:

%Writes
X(1).indexes = 1;
X(2).indexes = [1 2 3];
X(3).indexes = [1 2];

%Reads
a = X(1).indexes
b = cat(2,X.indexes)
c = X([2 4]);

Вы также можете использовать объект containers.Map. Это имеет те же преимущества, что и массив структур, но с большей гибкостью в том, как вы ссылаетесь на свои объекты. В то время как при использовании массива структур структура является ссылкой по индексу, использование объекта container.Map может ссылаться на каждую структуру, используя произвольное число (не целые числа около 1) или имя (непрактично для случаев 2 ^ 24). Это, вероятно, не лучший ответ для вас, но для справки примеры использования приведены ниже:

%Writes
X = containers.Map('keyType','uint32','valueType','Any');
X(1) = [1];
X(2) = [1 2 3];
X(3) = [1 2];
X(4) = [1 2 3 4];

%Reads
a = X(1);
b = cat(2,X.values);

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

%A start at cube.m.  Most of the code handles smartly reallocating the list of lines.
classdef cube < handle
    properties (SetAccess = private, GetAccess = public)
        numLines = 0
        intersectingLines = [];
    end
    methods (Access = public)
        function addLine(self, lineToAdd)
            if self.numLines == 0
                self.intersectingLines = lineToAdd;
                self.numLines = 1;
            elseif self.numLines>=length(self.intersectingLines)
                self.intersectingLines(length(self.intersectingLines)*2) = line();
                self.intersectingLines(self.numLines+1) = lineToAdd;
                self.numLines = self.numLines+1;
            else
                self.intersectingLines(self.numLines+1) = lineToAdd;
                self.numLines = self.numLines+1;
            end
        end
    end
end

%A start at line.m.  A near copy/paste of cube.m
    classdef line < handle
    properties (SetAccess = private, GetAccess = public)
        numCubes = 0
        intersectingCubes = [];
    end
    methods (Access = public)
        function addCube(self, cubeToAdd)
            if self.numCubes == 0
                self.intersectingCubes = cubeToAdd;
                self.numCubes = 1;
            elseif self.numCubes>=length(self.intersectingCubes)
                self.intersectingCubes(length(self.intersectingCubes)*2) = cube();
                self.intersectingCubes(self.numCubes+1) = cubeToAdd;
                self.numCubes = self.numCubes+1;
            else
                self.intersectingCubes(self.numCubes+1) = cubeToAdd;
                self.numCubes = self.numCubes+1;
            end
        end
    end 
end

Чтобы использовать эти классы в том виде, в котором они написаны, вам нужно вызывать add методов парами (очевидным обновлением на будущее является правильное перекрестное добавление. Тем временем (потому что я ленивый) мы определим вспомогательную функцию.

function crossAdd(cube, line)
cube.addLine(line);
line.addCube(cube);

Теперь пример использования:

%Create two class arrays of cubes and lines
allCubes(1) = cube;
allCubes(2) = cube;
allCubes(3) = cube;
allCubes(4) = cube;

allLines(1) = line;
allLines(2) = line;
allLines(3) = line;
allLines(4) = line;

%Define links (matching above "writes" examples)
crossAdd(allCubes(1), allLines(1));
crossAdd(allCubes(2), allLines(1));
crossAdd(allCubes(2), allLines(2));
crossAdd(allCubes(2), allLines(3));
crossAdd(allCubes(3), allLines(1));
crossAdd(allCubes(3), allLines(2));
crossAdd(allCubes(4), allLines(1));
crossAdd(allCubes(4), allLines(2));
crossAdd(allCubes(4), allLines(3));
crossAdd(allCubes(4), allLines(4));

%Use linked values
aLines = allCubes(1).getLines   %Only one intersecting line
bLines = allCubes(2).getLines   %Three intersecting lines
cubesFromSecondLine = bLines(2).getCubes %Three cubes here (2, 3, 4)

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

07.12.2012
Новые материалы

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

Скрытый технический долг в системах машинного обучения [NeurIPS 2015]
Что такое технический долг? Технический долг — это метафора, введенная Уордом Каннингемом в 1992 году, чтобы объяснить долгосрочные затраты, связанные с быстрым продвижением в разработке..

Алгоритм быстрой сортировки в Python
Всем привет, добро пожаловать на programminginpython.com . Здесь я покажу вам, как реализовать алгоритм быстрой сортировки в Python. В предыдущих статьях я рассмотрел Сортировку вставкой ,..

Как использовать манипулирование объектами в JavaScript
Объекты являются важным строительным блоком JavaScript. Они позволяют группировать свойства и методы вместе. Объект представляет собой набор свойств. Свойства идентифицируются с..

Разработка игр с помощью Godot Engine: мощный инструмент с открытым исходным кодом
Разработка игр — творческий и сложный процесс, требующий множества навыков и инструментов. Одним из наиболее важных инструментов является игровой движок, который представляет собой программную..

От XML к аннотациям: переход к современной конфигурации Spring
Введение Фреймворк Spring претерпел значительную эволюцию с момента своего создания. Одним из заметных изменений стал переход от конфигураций на основе XML к конфигурациям, управляемым..

Я люблю Руби!
Я люблю Руби! Мне это нравится по той же причине, по которой мне нравится программировать на Python. Он настолько интуитивно понятен, а встроенные методы упрощают решение проблем. Если вы..