【问题标题】:MATLAB load mat-file with wildcard (*) into current workspaceMATLAB 将带有通配符 (*) 的 mat 文件加载到当前工作区
【发布时间】:2015-07-31 03:49:09
【问题描述】:

我编写了一个函数,通过使用dir 捕获通配符然后调用load,将带有通配符的mat 文件加载到结构中。这是函数:

function S = loadw(varargin)
%LOADW Load variables from file into workspace, with wildcard (*) in file name

filename = varargin{1};

if(ismember('*', filename))
    [pathstr, ~, ext] = fileparts(filename);
    if(isempty(pathstr))
        pathstr = '.';
    end
    if(~strcmp(ext, '.mat'))
        filename = [filename '.mat'];
    end
    dirFiles = dir(filename);
    if(isempty(dirFiles))
        error(['Unable to read file ''' filename ''': no such file or directory.']);
    elseif(numel(dirFiles) == 1)
        varargin{1} = [pathstr filesep dirFiles(1).name];
        S = load(varargin{:});
    else
        S = cell(numel(dirFiles), 1);
        for iFile = 1:numel(dirFiles)
            varargin{1} = [pathstr filesep dirFiles(iFile).name];
            S{iFile} = load(varargin{:});
        end
    end
else
    S = load(varargin{:});
end

这很好用,但是它只能将文件加载到结构中,而不能像 load 那样加载到调用者工作区中。 如何修改此函数以设置调用方工作区中的变量?

我曾考虑使用assignin 来执行此操作,但这意味着我首先将变量加载到函数工作区,然后将它们传输到调用者工作区。我更喜欢不需要两次声明变量的方法。如果不重新实现load,这可能吗?或者,也许两次声明变量没有开销,因此使用assignin('caller',...) 实际上是一个有效的解决方案?

【问题讨论】:

    标签: matlab


    【解决方案1】:

    当你做线时

    S = load(varargin{:});
    

    它会将文件中的变量加载为SS{iFile} 的结构元素(视情况而定)。如果你不想这样,如果你只是想让变量直接进入工作区,你可以跳过赋值给S

    load(varargin{:});
    

    我通常更喜欢避免将变量直接加载到工作区,因为您永远无法确定文件中有哪些变量以及它可以对您的工作区做什么。

    所以作为一种替代方法,如果这是一个问题,一旦你将变量加载到S,你就可以编写另一个通过结构的块,提取字段名称(使用fieldnames函数) 然后直接将S.(fieldname) 成员重新分配给fieldname,在检查了它在工作区中不存在之后(使用exist(fieldname, 1))。

    您可以使用eval 自行完成作业。请注意,Mathworks 最近在很多情况下为结构和 they recommend this 引入了动态字段引用而不是 eval,但我认为这个用例(分配给以字段名称命名的变量)仍然需要 eval

    【讨论】:

    • 我想分配工作区中调用函数loadw的变量,就像调用load时分配的一样。我可以遍历字段名称并使用assignin('caller',...)(而不是evalin。我知道evalevalin 应该避免并且通常可以避免),但这意味着我声明了两次变量,正如我所写:一个我将它们加载到函数工作区的时间,以及第二次将它们分配给调用者工作区的时间。我想知道这是否可以避免。
    • 抱歉,错过了。您可以修改该函数,使其仅返回完整文件路径的列表,然后您可以对其进行迭代并加载到调用工作区中。还有这个stackoverflow.com/questions/1823668/…,它不是你要问的,但有一些可以修改的巧妙技巧。
    【解决方案2】:

    我确信唯一的选择是要么加载函数内的文件,然后使用assignin('caller',...),要么使用evalin('caller', 'load(...);')。在这两者之间,我选择后者,因为我认为避免两次声明变量值得遭受eval 函数的缺点。这是我现在的功能:

    function S = loadw(varargin)
    %LOADW Load variables from file into workspace, with wildcard (*) in file name
    
    filename = varargin{1};
    
    if(ismember('*', filename))
        [pathstr, ~, ext] = fileparts(filename);
        if(isempty(pathstr))
            pathstr = '.';
        end
        if(~strcmp(ext, '.mat'))
            filename = [filename '.mat'];
        end
        dirFiles = dir(filename);
        if(isempty(dirFiles))
            error(['Unable to read file ''' filename ''': no such file or directory.']);
        elseif(numel(dirFiles) == 1)
            varargin{1} = [pathstr filesep dirFiles(1).name];
            if(nargout > 0)
                S = load(varargin{:});
            else
                strLoadCommand = ['load(''' strjoin(varargin, ''', ''') ''');'];
                evalin('caller', strLoadCommand);
            end
        else
            if(nargout > 0)
                S = cell(numel(dirFiles), 1);
            end
            for iFile = 1:numel(dirFiles)
                varargin{1} = [pathstr filesep dirFiles(iFile).name];
                if(nargout > 0)
                    S{iFile} = load(varargin{:});
                else
                    strLoadCommand = ['load(''' strjoin(varargin, ''', ''') ''');'];
                    evalin('caller', strLoadCommand);
                end
            end
        end
    else
        if(nargout > 0)
            S = load(varargin{:});
        else
            strLoadCommand = ['load(''' strjoin(varargin, ''', ''') ''');'];
            evalin('caller', strLoadCommand);
        end
    end
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-03
      相关资源
      最近更新 更多