apply function to all fields in a structure array

56 ビュー (過去 30 日間)
checker
checker 2020 年 5 月 11 日
回答済み: George Abrahams 2022 年 12 月 29 日
Hi,
I have a structure array of the sort:
sa(1).F1.f1 = 1.1; sa(1).F1.f2 = 1.2;
sa(2).F1.f1 = 2.1; sa(2).F1.f2 = 2.2;
I'd like to find the max of all the fields held in F1 like
f1Max = max(arrayfun(@(x) x.F1.f1, sa));
f2Max = max(arrayfun(@(x) x.F1.f2, sa));
without having to explicity code each of F1's fields. Also prefer not to use eval based on field names. Pretty much thinking there's not really a one liner for this. Hints appreciated.
Chris

採用された回答

per isakson
per isakson 2020 年 5 月 12 日
編集済み: per isakson 2020 年 5 月 12 日
Another mix of structfun and arrayfun
>> max( cell2mat( arrayfun( @(S) structfun( @(f) f, S.F1 ), sa, 'uni',false ) ), [], 2 )
ans =
2.1
2.2
  1 件のコメント
checker
checker 2020 年 5 月 12 日
Ah, just so, thanks!

サインインしてコメントする。

その他の回答 (2 件)

dpb
dpb 2020 年 5 月 11 日
Why the nested structure? That's where the problem arises---convert to a struct array, S as
>> S=F1
S =
1×2 struct array with fields:
f1
f2
K>> arrayfun(@(s) structfun(@max,s),S,'UniformOutput',false)
ans =
1×2 cell array
{2×1 double} {2×1 double}
>>
If there's some reason this is absolutely mandatory, you can use fieldnames to return the field names of the struct programmatically and iterate that way. eval would not be needed but still awkward.
  1 件のコメント
checker
checker 2020 年 5 月 12 日
The nested structure results from the design of my parsing and type of data I'm parsing for, so it's hard to avoid.
I appreciate your response but the code does not provide the correct result, under the assumption that S=F1 should actually be S=sa.F1.
S=sa.F1 just pulls sa(1).F1. The rest of the code then pulls the max value of sa(1).F1 for each field (f1 and f2), which are scalars.
mxValues = arrayfun(@(s) structfun(@max,s),S,'UniformOutput',false)
mxValues{1}
ans =
1.1000
1.2000

サインインしてコメントする。


George Abrahams
George Abrahams 2022 年 12 月 29 日
For future reference, you could also use my fieldfun function on File Exchange / GitHub. Apart from being more concise and flexible, the main difference is that it outputs a structure with the fields of sa.F1.
sa(1).F1 = struct('f1',1.1,'f2',1.2,'f3',1.3);
sa(2).F1 = struct('f1',2.1,'f2',2.2,'f3',2.3);
sa(3).F1 = struct('f1',3.1,'f2',3.2,'f3',3.3);
fieldfun( @(varargin) max([varargin{:}]) , [sa.F1] )
% Returns struct with fields:
% f1: 3.1000
% f2: 3.2000
% f3: 3.3000
To add a little more detail:
  • [sa.F1] converts all of the nested structures in field F1 of structure array sa to an unnested structure array, i.e. a 1x3 struct with fields f1, f2, f3. This uses Comma-Separated Lists.
  • The anonymous function is passed the arguments @( sa(1).F1.fm , sa(2).F1.fm , sa(3).F1.fm ) for each field fm of sa.F1.
  • varargin puts these arguments into cell array { sa(1).F1.fm , sa(2).F1.fm , sa(3).F1.fm }, which [varargin{:}] converts into matrix [ sa(1).F1.fm , sa(2).F1.fm , sa(3).F1.fm ], which @max can process.

カテゴリ

Help Center および File ExchangeStructures についてさらに検索

製品


リリース

R2017b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by