如何找到在Matlab中完成某些结构的命令?

时间:2013-04-13 08:02:50

标签: matlab

假设a被定义为下面的结构。我试图找到与R的dput相同的命令但是错误here。例如,我知道下面的格式必须是struct('const',1,'terms',{{struct(),struct()}}),但我不知道结构中存储了什么,而不用像here这样的命令检查它,这很耗时。

那么我可以通过哪个命令看到在Matlab中生成结构的原始命令?

>> a

a =

    const: 1
    terms: {[1x1 struct]  [1x1 struct]}

3 个答案:

答案 0 :(得分:3)

<强>注释

  

您是否可以从使用结构切换到类?如果是这样,你可以创建一个模仿结构的模板,并且每次修改它时调用stack = dbstack来获取堆栈 - 然后将堆栈与更改一起存储。然后,可以从堆栈中的行号自动检索进行更改的命令。

作为评论中对此的后续请求,这里是一个提供结构功能的类的示例,并且还保留其分配的记录:

classdef utstruct
    properties (SetAccess = private)
        modifications
    end

    properties (Dependent, SetAccess = private)
        myStruct
    end

    properties (Access = private)
        m_struct
    end

    methods
        function self = utstruct(varargin)
            if nargin > 0
                self.m_struct = builtin('struct', varargin{:});
            else
                self.m_struct = builtin('struct');
            end
            % Should update self.modifications here
        end

        function B = subsref(self, s)
            if any(strcmp(s(1).subs, properties(self)))
                B = builtin('subsref', self, s);
            else
                B = subsref(self.m_struct, s);
            end
        end

        function A = subsasgn(self, s, b)
            self.m_struct = subsasgn(self.m_struct, s, b);

            newMod = builtin('struct');
            newMod.type = 'subsasgn';
            newMod.modData = {s b};
            newMod.stack = dbstack;
            self.modifications = [self.modifications; newMod];

            A = self;
        end

        function disp(self)
            disp(self.m_struct);
        end

        function names = fieldnames(self, varargin)
            names = fieldnames(self.m_struct, varargin{:});
        end

        function C = cat(self, dim, varargin)
            uts = cellfun(@(x)isa(x, 'utstruct'), varargin);
            varargin{uts} = cellfun(@(x)x.m_struct, varargin(uts));
            varargin = [{self.m_struct} varargin];
            self.m_struct = cat(dim, varargin{:});

            % Should update self.modifications here

            C = self;
        end

        function C = horzcat(self, varargin)
            C = self.cat(1, varargin{:});
        end

        function C = vertcat(self, varargin)
            C = self.cat(2, varargin{:});
        end

        function value = get.myStruct(self)
            value = self.m_struct;
        end
    end
end

在初始化/连接操作发生时,您应该添加一些代码来更新修改数组。

subsrefsubsasgn覆盖是这里的关键点,使其行为像结构(通过将所有活动推迟到实际结构),但其他覆盖如fieldnamesdisp做同样的事情。在subsasgn中,保留了对结构的所有赋值的记录,以及生成赋值的堆栈。

注意:为了与内置struct完全兼容,您可能应该覆盖更多方法,但这应该足以让您入门。请参阅Subclassing MATLAB Built-In Types

编辑:我让这个例子更加健壮。它现在是一个价值类 - 应该是 - 并且与串联一起使用。

修改:您可以通过重新定义函数struct(...)来避免使用查找和替换来重构现有的struct调用:

function s = struct(varargin)
% STRUCT    Overrides default struct function to provide unit-testable structs
%
%   Set global variable unitTestStructEnabled to true to enable this
%   function.
%
global unitTestStructEnabled;

if isempty(unitTestStructEnabled)
    unitTestStructEnabled = false;
end

if unitTestStructEnabled
    s = utstruct(varargin{:});
else
    s = builtin('struct', varargin{:});
end

你可能不希望它一直在你的路径上闲逛,因为当你第一次创建一个结构时你会得到一个警告(你可以把它关闭,但这可能会隐藏其他问题),所以你可能应该将它放在通常不在路径中的文件夹中,并暂时将其添加到单元测试的路径中(addpath / rmpath)。

答案 1 :(得分:1)

这是dumpvar函数的骨架,即tashuhka

的概念
function str = dumpvar(a)
        switch class(a)
        case 'double'
                if isempty(a)
                        str = '[]';  % bug when "a" is multidimensional and empty

                elseif isscalar(a)
                        str = num2str(a);

                elseif isrow(a)
                        str = strcat('[', dumpvar(a(1)));
                        for k = 2:size(a,2)
                                str = strcat(str,',',dumpvar(a(k)));
                        end;
                        str = strcat(str, ']');

                elseif numel(size(a)) == 2
                        str = strcat('[', dumpvar(a(1,:)));
                        for k = 2:size(a,1)
                                str = strcat(str,';',dumpvar(a(k,:)));
                        end;
                        str = strcat(str, ']');

                else
                        do_what_i_mean();
                end;

        case 'struct'
                fn = fieldnames(a);
                if isempty(fn)
                        str = 'struct()';

                elseif isscalar(a)
                        str = strcat('struct(''', fn{1},''',', dumpvar(a.(fn{1})));
                        for k=2:numel(fn)
                                str = strcat(str,',''',fn{k},''',', dumpvar(a.(fn{k})));
                        end;
                        str = strcat(str, ')');

                else
                        do_what_i_mean();
                end;

        otherwise
                do_what_i_mean();
        end;

        function do_what_i_mean()
                throwAsCaller(MException(...
                        'beingLazy:onSaturday:Fault', ...
                        'Storage of class "%s" and arity %d is not implemented yet. Would you?', ...
                        class(a), numel(size(a))...
                ));
        end;
end

将其保存在Matlab路径中某处的dumpvar.m文件中,然后使用以下代码片段对其进行测试:

a = struct(...
    'field1', 1,...
    'field2', [],...
    'field10', struct(...
        'field3', [1 2;2 3;3 4],...
        'field4', struct()...
     )...
);
disp(dumpvar(a));
eval(sprintf('b=%s;', dumpvar(a)));

请注意,此功能仍处于玩具阶段:它几乎无所不包(缺少对结构数组,单元格,字符,逻辑和其他基本类型的处理,更不用说用户定义的类了 - 呵呵,那些会是一个泡菜)它是由你完成你需要的任何功能。

答案 2 :(得分:1)

虽然它没有完全回答你的问题,但是Urs的vsize()可以帮助你:

% Create some complicated variable
v(1).a{1}=sparse(magic(3)+2i*magic(3));
v(2).a{2}={struct('FA',{'a','bb'},'FB',{magic(5),{}})};
v(2).b{2}=@(x) sind(x);

% Dissect        
P = vsize(v);

% -------------------------
%       1998       1998 B *   v = 2:1x2:struct.(2)
% CELL -----        360 B     v[].a = 2:1x1:cell
%       1750        248 B -   v[].a{} = 2:3x3:double.sparse.complex
% CELL -----       1014 B     v[].a = 2:1x2:cell
%       1750          0 B -   v[].a{} = 2:0x0:double
% CELL -----        894 B     v[].a{} = 2:1x1:cell
% STRUCT ---        782 B     v[].a{}{} = 2:1x2:struct.(2)
%       1748          2 B -   v[].a{}{}[].FA = 2:1x1:char
%       1744          4 B -   v[].a{}{}[].FA = 2:1x2:char
%       1544        200 B -   v[].a{}{}[].FB = 2:5x5:double
% CELL -----          0 B     v[].a{}{}[].FB = 2:0x0:cell
%       1544          0 B -   v[].b = 2:0x0:double
% CELL -----        152 B     v[].b = 2:1x2:cell
%       1544          0 B -   v[].b{} = 2:0x0:double
%       1512         32 B -   v[].b{} = 2:1x1:function_handle