2

我编写了一个脚本,可以让我在 Matlab 中手动导入测试期间记录的数据。

每次测试运行都会在文件中保存大约 2600 个变量.csv,每个变量都有 2 个标题行、两列数据并且;是分隔符。

文件名来自监控程序使用的内部 C 结构,因此属于这种类型:foo.bar.another.foo.bar.local_varname#VALUE.csv我想用它在 Matlab 中重新创建结构,以便仅将其保存在test_name.mat文件中。

很多时候它的local_varname长度超过 63 个字符,所以我有一些替换规则来缩短名称而不让 Matlab 截断名称(因此试图避免命名冲突)。

这是代码

clear all
clc

% Main names
path_self         = pwd;
backslash_indices = strfind(path_self,'\');
test_name         = path_self(backslash_indices(end)+1:end); % the directory name gives me the test_name

% Preallocation
filenames = cell(1,2600);
addresses = cell(1,2600);
i=0;

% Full list
MyFiles = dir(path_self); 

% Discard subdirectories and non interesting files
for k=1:length(MyFiles)
    if ~MyFiles(k).isdir,
        if ~isempty(strfind(MyFiles(k).name,'#VALUE.csv'))
            i=i+1;
            % Too many files
            if i > length(filenames)
                filenames = [filenames cell(1,100)];
                addresses = [addresses cell(1,100)];
            end
            % Naming Substitution Rules

            %%% INSERT HERE BUNCH OF RULES

            % Addresses and names
            filenames{i} = strrep(filename,'#VALUE.csv','');
            addresses{i} = fullfile(path_self, MyFiles(k).name);
        end
    end
end
filenames = filenames(1:i);
addresses = addresses(1:i);

% Check that no conflicts are created
if length(filenames) ~= length(unique(filenames))
    error('filenames not unique')
end

% Housekeeping #1
clear MyFiles backslash_indices i k path_self

% Import data
for j=1:length(filenames)
    % Read data
    Data = importdata(addresses{j}, ';', 2);
    % Assign data
    eval([filenames{j}, '.time   = Data.data(:,1)./1000000;']); % Converted in seconds
    eval([filenames{j}, '.values = Data.data(:,2);']);
    % Let's avoid data corruption
    clear Data
end

% Housekeeping #2
clear filenames addresses j 

% Save data struct
save(test_name, '-regexp', '^((?!name).)*$')

现在我的问题 在研究信息并帮助编写上述代码时,我经常发现人们不赞成使用eval(): 为什么会这样?在上述情况下,我可以避免吗?

谢谢

编辑 正如@wakjah 所建议的,我测试了一种containers.Map()方法。不幸的是不适合我们的需求,因为此时需要一个键列表并且访问数据并不完全友好(请记住,我有大约 2600 个变量,这意味着至少有相同数量的键)

至于@Dennis Jaheruddin 所问的问题,数据结构是可用的并且不会产生任何冲突,即使使用这些长变量名(假设两个连续的名称*.的长度小于 63 个字符)

*我很抱歉没有使用更好的技术术语

4

3 回答 3

4

从Mathworks 上的这个页面:

尽管 eval 函数非常强大和灵活,但它并不总是编程问题的最佳解决方案。与使用其他函数或语言结构的代码相比,调用 eval 的代码通常效率较低且更难阅读和调试。...

您可以轻松地使用括号符号来完成您的任务。一个简单的例子:

s = struct();
myFieldName = 'test';
s.(myFieldName) = myFieldValue;

这会将test结构中的字段设置smyFieldValue.

Loren也有这篇关于这个主题的博客文章。

编辑:由于您的要求是字段名称长于 63 个字符,另一种方法是使用该containers.Map对象。这是一个小例子:

>> m = containers.Map();
>> myFieldName = repmat('abcdefg', [1 10]); % 70 chars long
>> m(myFieldName) = 12345; 
>> m(myFieldName)

ans =

       12345
于 2013-03-28T12:34:02.257 回答
3

看了你想做的事后,我的第一个想法是你做的很奇怪。

超过 63 个字符的变量名基本上是自找麻烦。相反,我会推荐以下简单的解决方案:

使用具有两个字段的结构:

  • 文件名
  • 价值

这样,您的数据结构更加自然,您的所有文件只需要一个变量。


请注意,值可以是结构或数组,不限于单个字符串或数字。

我在这里能想到的唯一真正的缺点是自动完成功能适用于变量名,但不适用于它们的内容,但这应该是一个很小的代价。

于 2013-03-28T13:26:53.280 回答
0

您是否考虑过使用该函数genvarname从 生成有效的唯一变量名local_varname

于 2013-03-28T12:59:55.833 回答