2016-05-17 150 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