Matlab:如何用大量表达式优化代码

Matlab:如何用大量表达式优化代码,matlab,optimization,Matlab,Optimization,我有一个字符串数组TrajCompact(106x1)。 对于每个字符串,我想找到'00'、'11'、'22'、'33'、'44'、'12'、'21'等等,然后对它们进行计数。我创建了一个代码,给我一个正确的答案,但它不是效率:它很长,也不聪明。我的代码是 for k=1:106 %% Determinazione elementi diagonale matrice matchstarts_00(k) = regexp(TrajCompact(k,1), '0.+?0'); %for '00'

我有一个字符串数组TrajCompact(106x1)。 对于每个字符串,我想找到'00'、'11'、'22'、'33'、'44'、'12'、'21'等等,然后对它们进行计数。我创建了一个代码,给我一个正确的答案,但它不是效率:它很长,也不聪明。我的代码是

for k=1:106
%% Determinazione elementi diagonale matrice
matchstarts_00(k) = regexp(TrajCompact(k,1), '0.+?0'); %for '00'
matchcounts_00(k) = cellfun(@numel, matchstarts_00(k));

matchstarts_11(k) = regexp(TrajCompact(k,1), '1.+?1'); %for '11'
matchcounts_11(k) = cellfun(@numel, matchstarts_11(k));

matchstarts_22(k) = regexp(TrajCompact(k,1), '2.+?2'); %for '11'
matchcounts_22(k) = cellfun(@numel, matchstarts_22(k));

matchstarts_33(k) = regexp(TrajCompact(k,1), '3.+?3'); %for '11'
matchcounts_33(k) = cellfun(@numel, matchstarts_33(k));

matchstarts_44(k) = regexp(TrajCompact(k,1), '4.+?4'); %for '11'
matchcounts_44(k) = cellfun(@numel, matchstarts_44(k));
end

count_00=sum(matchcounts_00);    
count_11=sum(matchcounts_11);
count_22=sum(matchcounts_22);
count_33=sum(matchcounts_33);
count_44=sum(matchcounts_44);

你能给我建议优化它吗!谢谢

,这样您就可以在每个表上使用
findstr
而不是
regex
findstr实际上只是一个regex,但它也是一个Matlab函数——因此您可以并行使用它(这基本上消除了
for
循环的需要)。有几条路可以走:

假设您的单元阵列是:

Test = {'020103101adfiohjas','020123101a01dfasad'}
方法1:

tic
A = cellfun(@(x) size(findstr(x,'01'),2), Test, 'UniformOutput', 0)
total = sum(cell2mat(A))
toc

Elapsed time is 0.015609 seconds.
方法2:

T = char([Test{:}])
tic
total = size(findstr(T,'01'),2)
toc

Elapsed time is 0.007199 seconds.
方法2要求将所有单元格折叠为一个大单元格,并使用findstr快速查找字符数组中“01”的编号


方法1功能更强大,您可以使用它来获取“01”等的所有索引,但从tictoc判断,方法2更快。

regexp
如果将多个字符串指定为单元格数组,则可以接受多个字符串进行匹配。事实上,您已经通过传递它
TrajCompact(k,1)
而不是
TrajCompact{k,1}
传递了一个单元素单元格数组。如果您使用了后者,您就可以使用
numel
而不是
cellfun
来获取计数。但由于您实际上有多个字符串要匹配,因此您可以一次完成所有操作:

matchstarts_00 = regexp(TrajCompact, '0.+?0');
matchcounts_00 = cellfun(@numel, matchstarts_00);
您还可以对要测试的每个正则表达式的操作进行矢量化,但由于您希望对
TrajCompact
元素和给定正则表达式的每个组合都有一个结果,因此需要使用循环来执行此操作

您的示例仅为矩阵对角线上的索引对创建计数,但您的问题表明您需要矩阵的所有索引对。无论哪种方式,都可以设置数组,每个正则表达式一个元素,每个数字一个数组,存储为单元格数组。对于所有组合(包括“12”“21”等):

或对于对角线:

[digits{1:2}] = deal(0:4);
然后可以在该数组上循环,为每个组合组装正则表达式并获得计数。我假设“开始”数组实际上不需要被调用,所以我不是将其存储在单元格数组中,而是在每次迭代中覆盖相同的变量,但是如果需要,应该清楚地知道如何将其存储在单元格数组中

matchcounts = cell(size(digits{1}));
for k = 1:numel(matchcounts)
    matchstarts = regexp(TrajCompact, sprintf('%d.+?%d', digits{1}(k), digits{2}(k)));
    matchcounts{k} = cellfun(@numel,matchstarts);
end

恐怕我不知道matlab,但只是在概念层面上,这段代码需要对每个单独的regexp调用多次通过相同的字符串。算法上的最佳解决方案(如果字符串相对较大,还包括内存方面的解决方案)将能够在通过字符串的单个过程中找到所有这些匹配项,但恐怕我不知道通过MatlabAPI/语言实现这一点的方法。希望有人能在这里投球。谢谢你的建议!我尝试了不同的方法,但我又遇到了问题!:|谢谢你的建议!您的方法适用于两个数字连续的情况,但我也希望找到不连续的数字。例如,在这个sting'021(23)(12)32131231(32)(13)(23)1321(32)303231213231(23)'我必须找到7'01',而用你的方法我找到0'01'(等等,你是如何找到7的?只有2个零对吗?对不起,我找到了1'01'并且使用你的方法0。我写错了。我还有一个问题:我想使用相同的代码来找到相同的元素,但是在()中:例如(11),(12),(13),等等。我尝试用不同的方式修改sprintf:例如matchstarts=regexp(TrajCompact,sprintf(“(%d.+?%d)”,数字{1}(k),数字{2}(k)));但是代码没有给出正确的答案。我阅读了有关sprintf的信息,但它不支持方括号…我如何解决这个问题?感谢
sprintf
不是这里的重要函数。它只是在这里使用
数字中的数值来构建进入
regexp
的正则表达式字符串o上面的示例将导致
regexp(TrajCompact,”(0.+?0)
。问题是
是正则表达式中的特殊字符。要将它们作为文字字符进行匹配,需要使用正则表达式中前面的
\
对它们进行转义。但是由于
\
也是
sprintf
模式中的特殊字符,因此需要对其进行双重转义,以便
sprintf
忽略斜杠和
regexp
看到它们:
\\(%d.+?%d\\)
谢谢!昨天我只尝试了括号前的一个“\”:两个解决了问题!
matchcounts = cell(size(digits{1}));
for k = 1:numel(matchcounts)
    matchstarts = regexp(TrajCompact, sprintf('%d.+?%d', digits{1}(k), digits{2}(k)));
    matchcounts{k} = cellfun(@numel,matchstarts);
end