2013-04-13 18 views
2

假設a被定義爲下面的結構。我試圖找到對R的輸入的等效命令,但是錯誤here。例如,我知道下面的格式必須是struct('const',1,'terms',{{struct(),struct()}}),但我不知道存儲在結構中的內容沒有使用像here這樣的命令檢查它是非常耗時的。如何在Matlab中查找某個結構完成的命令?

那麼通過哪個命令我可以看到原始命令在Matlab中生成一個結構?

>> a 

a = 

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

你可以通過與「字段名」命令的結構的所有級別遞歸去。 – tashuhka

+0

@tashuhka但我想獲得結構產生的原始命令,而不需要重新輸入內容。對於我來說,用一個非常大的結構來做它是沒有彈性的,這個命令會對測試有很大的幫助。必須有一些命令來做到這一點。 – hhh

+0

輸入'a =',然後在鍵盤上按下。控制檯會找到以'a ='開頭的最後一行。除非你在談論你沒有產生的結構。在這種情況下,我認爲這是不可能的... – wakjah

回答

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

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

請注意,此功能仍處於一個玩具階段:它接近窮舉(缺乏對結構數組,單元,char,邏輯和其他基本類型的處理,更不用說用戶定義的類--- hehe,那些將是一個pickle),它的意思是由你完成無論您需要什麼功能。

+0

事實上,Matlab沒有像這樣的東西或者像R的'dput'默認會觸發我們正在重塑車輪的鈴聲。如果我從頭開始,最簡單的方法是避免使用類,並以某種方式存儲作業? – hhh

+0

@hhh這是我的觀點,不是一個事實:在Matlab中'dput'的等價物將是'save',區別在於1)輸出是機器可讀的,不是人類可讀的; 2)輸出到文件,而不是屏幕。 可能是因爲Matlab設計者認爲IDE對於那些想要深度嵌套數據的人來說足夠了,而二進制文件更適合於存儲和檢索數據。 'dput'可用於兩個目的。有一些控制檯功能可以檢查數據(例如'disp','display'),但這不是你想要的。 – 2013-04-13 21:02:50

+0

@hhh(續)當我提出這個「數據解析器」時,我真誠地做到了這一點:面對你的任務,我將如何繼續。我的罪孽對其他人的代碼沒有多少耐心,因此我經常開始重新發明輪子。但顯然沒有車輪在第一位,或被埋得太深...... – 2013-04-13 21:04:18

1

雖然它並不能完全解答您的問題,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}[email protected](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 
+0

+1這可以變得方便,謝謝你的建議。 – hhh