如何从 Matlab 数组中删除特定 struct.field 值的结构

How to remove structs from Matlab array for specific struct.field values

每次我尝试按字段编辑结构数组时,我发现我真的需要花几周的时间来尝试真正学习 Matlab。现在,我有一个结构数组,其中每个结构都有以下行的字段:

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

这些字段中的每一个都是一个字符串。我还有一个字符串元胞数组:

y = {'apple', 'banana', 'palm of granite'}

我想删除所有 x.fruit 在 y 中的结构(例如 x.fruit == 'apple'),但似乎找不到其他方法而不是通过循环 y.

我希望得到类似以下内容的东西:

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

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

如果 x 的每个元素仅包含 fruit 字段的字符串,您可以通过以下方式轻松实现。

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

或更简短

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

{x.fruit} 语法将每个 structfruit 的所有值组合到一个元胞数组中。然后,您可以在字符串元胞数组上使用 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}));