2

假设a定义为下面的结构。我试图找到与 R 的 dput 等效的命令,但在这里出错。例如,我知道下面的内容必须是这种形式struct('const',1,'terms',{{struct(),struct()}}),但我不知道结构中存储了什么,而无需使用类似here的命令进行检查,这很耗时。

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

>> a

a =

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

3 回答 3

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您可能应该覆盖更多的方法,但这应该足以让您入门。请参阅子类化 MATLAB 内置类型

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

编辑:您可以通过重新定义函数来避免使用查找和替换来重构现有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)。

于 2013-04-13T09:53:05.930 回答
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

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

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)));

请注意,此函数仍处于玩具阶段:它几乎是穷尽的(缺乏对结构数组、单元格、字符、逻辑和其他基本类型的处理,更不用说用户定义的类 --- 呵呵,那些将是一个泡菜) 并且它意味着由您使用您需要的任何功能来完成。

于 2013-04-13T10:39:03.020 回答
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
于 2013-04-13T15:57:58.040 回答