OBJ-C: Getting the minimum/maximum value in a NSMutableArray
Asked Answered
F

5

10

I want to get the maximum and minimum values of a NSMutableArray so I can create a core-plot plotspace and graph based around those max and min values.

My code is as follows:

NSMutableArray *contentArray = [NSMutableArray arrayWithCapacity:100];
NSUInteger i;
for (i=0; i<60; i++){
id x = [NSNumber numberWithFloat:i*0.05];
id y = [NSNumber numberWithFloat:1.2*rand()/(float)RAND_Max + 0.6];
[contentArray addObject:[NSMutableDictionary dictionaryWithObjectsAndKeys:x, @"x", y, @"y", nil]];
}

self.dataForPlot = contentArray;

CPXYPlotSpace *plotSpace = (CPXYPlotSpace *)graph.defaultPlotSpace;
plotSpace.xRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromFloat() length:CPDecimalFromFloat()];
plotSpace.yRange = [CPPlotRange plotRangeWithLocation:CPDecimalFromFloat() length:CPDecimalFromFloat()];

What do I fill in the blanks for xRange and yRange assignment if I want the graph to span only the space of what's specified in contentArray?

Fancy answered 26/2, 2010 at 19:17 Comment(0)
C
20

In this case, you should use -[CPPlotSpace scaleToFitPlots:]. For more general calculations on array values, read on...

This is an ideal use for Key-Value coding and associated array operators. In your example,

float maxX = [[contentArray valueForKeyPath:@"@max.x"] floatValue];
float minY = [[contentArray valueForKeyPath:@"@min.x"] floatValue];

float maxY = [[contentArray valueForKeyPath:@"@max.y"] floatValue];
float minY = [[contentArray valueForKeyPath:@"@min.y"] floatValue];

The array operators call valueForKeyPath: on the contentArray which gives an array built by calling the same valueForKeyPath: on each member of the array with the key path to the right of the array operator (i.e. @min and @max). The orignal call then applies the given operator to the resulting array. You could easily define a category on NSArray to give you back a struct of min/max values:

typedef struct {
  float minX; 
  float minY;
  float maxX;
  float maxY;
} ArrayValueSpace;

@implementation NSArray (PlotSpaceAdditions)
- (ArrayValueSpace)psa_arrayValueSpace {
  ArrayValueSpace result;

  result.maxX = [[contentArray valueForKeyPath:@"@max.x"] floatValue];
  result.minX = [[contentArray valueForKeyPath:@"@min.x"] floatValue];

  result.maxY = [[contentArray valueForKeyPath:@"@max.y"] floatValue];
  result.minY = [[contentArray valueForKeyPath:@"@min.y"] floatValue];

  return result;
}
Cheiron answered 26/2, 2010 at 19:46 Comment(3)
Thanks Barry, your response was very helpful. Do you know if there is an auto-adjustment feature for axises as well?Fancy
The CPAxis class does support an automatic labeling policy (CPAxisLabelingPolicyAutomatic). The axis will, I think, automatically span the plot space so you just need to set the labeling policy to automatic and then tell it to relabel when the plot space changes size.Cheiron
@BarryWark What if I have 2 or more different arrays to be plotted in the same graph area? How can I take the one smallest and one largest Y value of all the arrays?Coad
D
1

You can find max and min values when you fill it, but it would work just when used in your snippet. If you want something more generic you should simply go through the list and searching for it.

// contentArray already defined
int maxX = 0, minX = 1000, maxY = 0, minY = 1000;

for (int i = 0; i < [contentArray count]; ++1)
{
   int curX = [[[contentArray objectForKey:@"x"] objectAtIndex:i] integerValue];
   int curY = [[[contentArray objectForKey:@"y"] objectAtIndex:i] integerValue];

   if (curX < minX)
     minX = curX;
   else if (curX > maxX)
     maxX = curX;

   if (curY < minY)
     minY = curY;
   else if (curY > maxY)
     maxY = curY;
}
Dibb answered 26/2, 2010 at 19:27 Comment(0)
P
0

You could use fast enumeration through the array. .

NSUInteger  maxX = 0;
NSUInteger  minX = 0xFFFFFFFF; //(for 32 bit)
NSUInteger  maxY = 0;
NSUInteger  minY = 0xFFFFFFFF; //(for 32 bit)
for ( NSDictionary *dict in contentArray ) 
{
    NSUInteger   newX = [[dict objectForKey:@"x"] integerValue];
    NSUInteger   newY = [[dict objectForKey:@"y"] integerValue];


    if (maxX > newX) maxX = newX;
    if (minX > newX) minX = newX;
    if (maxY > newY) maxY = newY;
    if (minY > newY) minX = newY;
}
Pneumatology answered 26/2, 2010 at 19:36 Comment(1)
I don't know for a fact that this is faster, but for the final assignment you could use: maxX = MAX(maxX, newX); etc...Neel
S
0

if you have NSMutableArray of NSDictionary objects you can use this:

-(float)findMax:array arrayKey:obj {
    float max = [[[array objectAtIndex:0] objectForKey:obj] floatValue];
    for ( NSDictionary *dict in array ) {
        if(max<[[dict objectForKey:obj] floatValue])max=[[dict objectForKey:obj] floatValue];
    }
    return max;
}

-(float)findMin:array arrayKey:obj {
    float min = [[[array objectAtIndex:0] objectForKey:obj] floatValue];
    for ( NSDictionary *dict in array ) {
        if (min > [[dict objectForKey:obj] floatValue])min = [[dict objectForKey:obj] floatValue];
    }
    return min;
}

You would access methods like this if in another class:

GraphData *c=[[GraphData alloc] init];
float maxY=[c findMax:plotData arrayKey:[NSNumber numberWithInt:1]]; //1 or 0 depending on axis 
[c release];
Slumberland answered 7/8, 2011 at 16:58 Comment(0)
M
0

//This gives Max and Min Value in NSMutableArrray -(void)FindingMinAndMaxValueInNSMutableArray{

NSMutableArray *array=[[NSMutableArray alloc]initWithObjects:@"0.987",@"0.951",@"0.881",@"0.784",@"0.662",@"0.522",@"0.381",@"-0.265",@"-0.197", @"0.189",@"-0.233",@"0.310",@"0.402",@"0.402",@"0.988",@"0.633",@"0.661",@"0.656",@"0.617",@"0.634",@"0.690",@"0.767",@"0.836",nil];

NSLog(@"The Array Value is %@",array);
NSLog(@"The Array Count is %lu",(unsigned long)array.count);

NSNumber *maxValue = [array valueForKeyPath:@"@max.doubleValue"];
NSLog(@"The maxValue is %@",maxValue);
NSString *str=[NSString stringWithFormat:@"%@",maxValue];
NSInteger path=[array indexOfObject:str];
NSIndexPath *indexpath=[NSIndexPath indexPathForItem:path inSection:0];
NSLog(@"Max Value = %@ and index = %ld",maxValue,(long)indexpath.row);


NSNumber *minValue = [array valueForKeyPath:@"@min.doubleValue"];
NSLog(@"The minValue is %@",minValue);
NSString *str1 = [NSString stringWithFormat:@"%@",minValue];
NSInteger path1 = [array indexOfObject:str1];
NSIndexPath *indexPath1 = [NSIndexPath indexPathForItem:path1 inSection:0];
NSLog(@"Min Value =%@ and index = %ld",minValue,(long)indexPath1.row);

}

Mella answered 30/5, 2019 at 7:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.