2016-05-17 907 views
0

每次尝试编辑字段结构数组时,我发现我真的需要花几周时间来尝试真正学习Matlab。现在,我有结构的数组,每个结构有场沿着线:如何从Matlab数组中删除特定struct.field值的结构

x.fruit, x.color, x.season, x.source, x.flibbertigibbet 

每个字段是一个字符串。我也有一个字符串单元阵列:

Y = {“苹果”,“香蕉”,“花岗岩的手掌”}

我想删除所有结构,其中x.fruit是在Y(EGX水果=='苹果'),但似乎无法找到一种方式来做到这一点,而不是通过循环y。

我希望沿着线的东西:

bad_idx = [x(:).fruit in y]; 
x(bad_idx) = []; 

这是可行的?有没有办法使用cellfun来做到这一点?

回答

1

如果x的每个元素仅包含fruit字段的字符串,则可以通过以下方式轻松完成此操作。

toremove = ismember({x.fruit}, 'apple') 
x(toremove) = []; 

或者更简单地

x = x(~ismember({x.fruit}, 'apple')); 

{x.fruit}语法结合了所有的fruit每个struct的值转换成一个单元阵列。然后你可以在字符串的单元阵列上使用ismember来比较每一个到'apple'。这将产生一个大小为x的逻辑数组,可用于索引x

你也可以使用类似strcmp而不是上面的ismember

x = x(~strcmp({x.fruit}, 'apple')); 

更新

如果每个x(k).fruit包含一个单元阵列,则可以使用与上述类似的方法与组合cellfun的方法。

x(1).fruit = {'apple', 'orange'}; 
x(2).fruit = {'banana'}; 
x(3).fruit = {'grape', 'orange'}; 

x = x(~cellfun(@(fruits)ismember('apple', fruits), {x.fruit})); 

%// 1 x 2 struct array with fields: 
%//  fruit 

如果你想检查多种类型的水果立即删除,你可以做类似的事情。

%// Remove if EITHER 'apple' or 'banana' 
tocheck = {'apple', 'banana'}; 
x = x(~cellfun(@(fruits)any(ismember({'apple', 'banana'}, fruits)), {x.fruit})); 

%// Remove if BOTH 'apple' and 'banana' in one 
x = x(~cellfun(@(fruits)all(ismember({'apple', 'banana'}, fruits)), {x.fruit})); 
+0

这些方法对单个水果工作正常,但我有一个列表。我是否需要循环遍历单元格数组中包含的水果(即y),从x中移除每一个水果,还是有更多的'Matlab-y'方法来使用隐式循环来做到这一点? – user1245262

+0

@ user1245262已更新以包含该用例。 – Suever