2

令 strCellArr 为 4000*1 的单元格数组。每个单元格都是一个字符串。

判断每个单元格是否有长度为 100 的字符串的最快方法是什么?

换句话说,我想要一些与

a= true;
For (i =0; i =length(strCellArr); i++)
    if length(strCellArr{i}) ~= 100
         a = false;
    end
end

一个相关的问题:

我可以将数组转换为 4000*100 字符数组

charArr = char(strCellArr);

但是,这将在不包含 100 个字符的行中引入空格。所以如果第 34 行只有 30 个字符。然后

charArr(34)(50)

将返回一个空格。

如何检查每个字符是否只是某些字符,在我的情况下(A、T、C 或 G)。有没有办法在不使用 for 循环的情况下做到这一点?

4

3 回答 3

6

哦,我只是喜欢以“最快的方法是什么……”开头的问题

这里有一些替代方案和比较:

% Initalize

map = 'CATG';     
strCellArr = cellfun(@(x) map(randi(4,100,1)),cell(4000,1), 'UniformOutput', false);


% Your original method 
tic
a = true;
for el = strCellArr
    if length(el{1}) ~= 100
         a = false;
         break;
    end
end
toc

% My solution 
tic
a = all(cellfun('length', strCellArr) == 100);
toc

% Dang Khoa's method
tic
a = all( cellfun(@(x) length(x) == 100, strCellArr) );
toc

% Engineero's method
tic
a = all(cellfun(@length, strCellArr) == 100);
toc

结果:

Elapsed time is 0.001158 seconds. % loop
Elapsed time is 0.000455 seconds. % cellfun; string argument
Elapsed time is 0.031897 seconds. % cellfun; anonymous function
Elapsed time is 0.006994 seconds. % cellfun; function handle

鲜为人知的事实:字符串输入cellfun指的是直接内置到cellfun二进制文件中的函数,因此不需要评估匿名函数。换句话说,cellfun不必在每次迭代时都通过 MATLAB 解释器,从而使这变得快速:)

现在,你问题的第二部分:

% Engineero
tic
A = 'ATCG';
all(all(ismember(char(strCellArr), A)));
toc

% My solution 
tic
C = char(strCellArr);
~any(C(:)==' ');
toc

结果:

Elapsed time is 0.061168 seconds. % ismember
Elapsed time is 0.005098 seconds. % direct comparison to whitespace

之所以出现这种差异,是因为ismember它是在 MATLAB m 代码中实现的,并且充斥着旨在使用户友好的代码(错误检查、错误、警告等)、复杂的概括、循环结构和许多其他东西,这些都是一种性能惩罚。

由于我们事先知道在将数组转换为时只会将空格添加到数组中char,因此我们不必式检查, , ,的出现'A',而只需检查它们的缺失。意思是,只需寻找那些空间:)'C''T''G'

不用说,这些时间几乎可以忽略不计,这一切都是精神上的自慰,而不是真正有用。但它的乐趣!:)

于 2013-06-12T23:35:11.330 回答
3

对于您的第一个问题,您可以使用all(cellfun(@length, strCellArr) == 100),如果单元格中的每个元素的长度为 100 个元素,它将返回 1 表示“真”。

对于第二个问题,您可以使用all(ismember(charArr, A))where A = ['A', 'T', 'C', 'G']。有关更多信息,请参阅allismember的文档。

于 2013-06-12T22:12:13.507 回答
3

对于您的第一个问题:这听起来像是cellfun. cellfun允许您对元胞数组中的每个元胞进行操作。(顺便说一句,arrayfun让你做同样的事情,但在一个常规的阵列上)。(请注意,您的原始代码不是 MATLAB 语法,尤其是for循环。)

所以你可以做类似的事情

res = cellfun(@(x) length(x) == 100, strCellArr);

在这里,res将是 a ,logical因为==条件将评估为 0 或 1。然后,您可以查看all结果是否为 1,即所有字符串strCellArr的长度为 100:

a = all(res);
if a == 0
    disp('One or more strings does not have 100 characters!');
else
    disp('All strings have 100 characters!');
end
于 2013-06-12T22:12:13.793 回答