我是 MATLAB 的新手,我很难理解数组操作和元素操作之间的微妙之处。我正在处理一个大型数据集,我发现最简单的方法并不总是最快的。我有一个非常大的字符串元胞数组,就像这个简化的例子一样:
% A vertical array of same-length strings
CellArrayOfStrings = {'aaa123'; 'bbb123'; 'ccc123'; 'ddd123'};
我正在尝试提取一个子字符串数组,例如:
'a1'
'b1'
'c1'
'd1'
我对这样的元素引用感到非常满意:
% Simple element-wise substring operation
MySubString = CellArrayOfStrings{2}(3:4); % Expected result is 'b1'
但我无法一次性计算出引用它们的符号,如下所示:
% Desired result is 'a1','b1','c1','d1'
MyArrayOfSubStrings = CellArrayOfStrings{:}(3:4); % Incorrect notation!
我知道 Matlab 能够执行非常快速的数组操作,例如 strcat,所以我希望有一种以类似速度工作的技术:
% An array-wise operation which works quickly
tic
speedTest = strcat(CellArrayOfStrings,'hello');
toc % About 2 seconds on my machine with >500K array elements
我尝试过的所有使用幕后迭代的 for 循环和函数在我的数据集上运行速度太慢。是否有一些数组符号可以做到这一点?有人能够纠正我对元素方式和数组方式操作的理解吗?!非常感谢!
最佳答案
I can't work out the notation to reference them all in one go, like this:
MyArrayOfSubStrings = CellArrayOfStrings{:}(3:4); % Incorrect notation!
这是因为大括号 ( {}
) 返回 comma-separated list ,相当于把这些单元格的内容写成下面这样:
c{1}, c{2}, <i>and so on</i>...
.
当下标索引仅引用一个 元素时,MATLAB 的语法允许在花括号后使用括号 ( ()
) 并进一步提取子数组(在您的情况下为子字符串)。但是,当逗号分隔列表包含多个项目时,此语法是被禁止的。
那么有哪些选择呢?
使用
for
loop :MyArrayOfSubStrings = char(zeros(numel(CellArrayOfStrings), 2)); for k = 1:size(MyArrayOfSubStrings, 1) MyArrayOfSubStrings(k, :) = CellArrayOfStrings{k}(3:4); end
使用
cellfun
(Dang Khoa's 答案的轻微变体):MyArrayOfSubStrings = cellfun(@(x){x(3:4)}, CellArrayOfStrings); MyArrayOfSubStrings = vertcat(MyArrayOfSubStrings{:});
如果你原来的元胞数组包含固定长度的字符串,你可以按照Dan的建议并将元胞数组转换为字符串数组(字符矩阵),对其进行整形并提取所需的列:
MyArrayOfSubStrings =vertcat(CellArrayOfStrings{:}); MyArrayOfSubStrings = MyArrayOfSubStrings(:, 3:4);
使用更复杂的方法,例如正则表达式:
MyArrayOfSubStrings = regexprep(CellArrayOfStrings, '^..(..).*', '$1'); MyArrayOfSubStrings = vertcat(MyArrayOfSubStrings{:});
有很多解决方案可供选择,请选择最适合您的解决方案 :) 我认为借助 MATLAB 的 JIT 加速,在大多数情况下一个简单的循环就足够了。
另请注意,在我的所有建议中,所获得的子字符串单元格单元格数组被转换为字符串数组(矩阵)。这只是为了举例;显然,如果您决定这样做,您可以将子字符串存储在元胞数组中。
关于matlab - Matlab 中元胞数组的子字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19299608/