ios - Nested NSArray filtering -


i have need obtain maximum value of property of collection of custom objects of same class. objects stored in nsarray, , property happens nsarray of numbers.

let me explain in detail:

nsarray *samples; // of cmdata, 4000 elements 

cmdata class models sample, specific moment in time, of set of different channels can have different values.

@interface cmdata : nsobject @property (nonatomic) nsuinteger timestamp; @property (nonatomic, strong) nsarray *analogchanneldata; // of nsnumber, 128 elements @end 

(i have stripped other properties of class not relevant question)

so example, sample[1970] be:

sample.timestamp = 970800 sample.analogchanneldata = <nsarray>     [     [0] = @(153.27)     [1] = @(345.35)     [2] = @(701.02)     ...     [127] = @(-234.45)     ] 

where each element [i] in analogchanneldata represents value of specific channel timestamp 970800

now want obtain maximum value 4000 samples channel 31. use following code:

nsuinteger channelindex = 31; nsmutablearray *values = [[nsmutablearray alloc] init]; // of nsnumber // iterate array of samples , each 1 obtain value  // specific channel , store value in new array (cmdata *sample in samples) {     [values addobject:sample.analogchanneldata[channelindex]]; } // maximum  nsnumber *maxvalue = [values valueforkeypath:@"@max.self"]; 

i want replace programming structure filter through nspredcicate or use valueforkeypath: obtain maximum of data need.

anyone knows how without loop? using nspredicates and/or valueforkeypath?

thank in advance help.

update 1

finally benckmarked for-loop version against keypath version (see accepted answer) , runs faster better go loop. recalling lessons algorithms classes, implemented faster version doesn't need array store values. iterate on selected channel , choose maximum in each iteration. far fastest version.

so:

  • version 1: loop (see code above)
  • version 2: version custom property (see selected answer marcus, update 2)
  • version 3: new code

code version 3:

nsuinteger channelindex = 31; nsnumber *maxvalue = @(-infinity); (cmtdata *sample in samples) {     nsnumber *value = sample.analogchanneldata[channelindex];     if (value) { // allow possibility of nsnull values in nsarray         if ([value compare:maxvalue] == nsordereddescending)             maxvalue = value;     } } // maximum in maxvalue @ end of loop 

performance:

after 20.000 iterations in ios simulator:

  • version 1: 12.2722 sec.
  • version 2: 21.0149 sec.
  • version 3: 5.6501 sec.

the decision clear. i'll use third version.

update 2

after more research, clear me kvc not work infividual elements in inner array. see following links: kvc nsarrays of nsarrays , collection accessor patterns to-many properties

anyway because wanted compute maximum of elements better iterate array use tricks make kvc work.

you can solve using key value coding , collection operators.

nsnumber *result = [sample valueforkeypath:@"@max.analogdatachannel"]; 

update 1

as arcanfel mentioned, can join arrays together:

nsnumber *result = [samples valueforkeypath:@"@max.@unionofarrays.@analogchanneldata"]; 

i suggest reading documentation both linked to. there powerful features in there.

update 2

further hrd's answer, has solution, need combine changes kvc.

add propert cmdata object currentchannel. can call

[samples setvalue:@(channelindex) forkey:@"currentchannel"]; 

which set in every instance in array. call:

[samples valueforkeypath:@"@max.analogdataforcurrentchannel"]; 

then done.


Comments

Popular posts from this blog

java - Run a .jar on Heroku -

java - Jtable duplicate Rows -

validation - How to pass paramaters like unix into windows batch file -