设置:
我有一个 21 x 3 元胞数组。
前 2 列通常是字符串或字符数组,但也可能是字符串或字符数组的 1xn 个单元格(如果在我的脚本上下文中存在多个表示相同含义的替代字符串)。第三个元素是一个数字。
我希望返回与第 1 列中此元胞数组中包含的字符串或字符数组(但类型不必匹配)完全匹配的索引,如果第 1 列不匹配,然后是第 2 列。
我可以使用以下内容:
find(strcmp( 'example', celllist(:,1) ))
find(strcmp( 'example', celllist(:,2) ))
这些会将相应的索引与顶级元胞数组中的任何字符串/字符数组相匹配。当然,这不会匹配顶级元胞数组内字符串元胞内的任何字符串。
是否有一种优雅的方式来匹配这些字符串(即不使用 for、while 或类似的循环)?如果单元格包含匹配项或单元格内的单元格在其任何单元格中包含完全匹配项,我希望它返回主单元格数组的索引(1 到 21)。
最佳答案
cellstr
函数是你的 friend ,因为它将以下所有内容转换为字符元胞数组:
- 字符,例如
cellstr( 'abc' ) => {'abc'}
- 字符单元格,例如
cellstr( {'abc','def'} ) => {'abc','def'}
- 字符串,例如
cellstr( "abc" ) => {'abc'}
- 字符串数组,例如
cellstr( ["abc", "def"] ) => {'abc','def'}
那么你不必关心变量类型,只需执行 ismember
即可检查每个元素,我们可以假设它是一个字符单元格。
我们可以设置一个测试:
testStr = 'example';
arr = { 'abc', 'def', {'example','ghi'}, "jkl", "example" };
% Expected output is [0,0,1,0,1]
通过循环执行此操作以更好地理解逻辑,如下所示:
isMatch = false(1,numel(arr)); % initialise output
for ii = 1:numel(arr) % loop over main array
x = cellstr(arr{ii}); % convert to cellstr
isMatch(ii) = any( ismember( testStr, x ) ); % check if any sub-element is match
end
如果你想避免循环*,那么你可以使用 cellfun
来代替这一行。
isMatch = cellfun( @(x) any( ismember( testStr, cellstr(x) ) ), arr );
% >> isMatch = [0 0 1 0 1]
因此,对于您的情况,您可以在两列上运行此代码,并应用一些简单的逻辑来选择您想要的列
isMatchCol1 = cellfun( @(x) any( ismember( testStr, cellstr(x) ) ), arr(:,1) );
isMatchCol2 = cellfun( @(x) any( ismember( testStr, cellstr(x) ) ), arr(:,2) );
如果您想要行索引而不是逻辑数组,则可以使用 find
包装输出。函数,即 isMatchIdx = find(isMatch);
.
*这只能在视觉上避免循环,cellfun
基本上是一个伪装的循环设备,但它至少节省了我们初始化输出的时间。
关于arrays - MATLAB 在单元格数组中搜索,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73530869/