2010-02-26 13 views
10

Desidero ottenere i valori massimi e minimi di un NSMutableArray in modo che sia possibile creare un plottaggio e grafico di core-plot basato su quei valori massimo e minimo.OBJ-C: Ottenere il valore minimo/massimo in un NSMutableArray

Il mio codice è il seguente:

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()]; 

Che cosa devo riempire gli spazi vuoti per xrange e YRange assegnazione se voglio il grafico si estendono solo lo spazio di ciò che è specificato nel contentArray?

risposta

0

È possibile trovare i valori massimi e minimi quando lo si riempie, ma funzionerebbe solo se utilizzato nel frammento. Se vuoi qualcosa di più generico, devi semplicemente consultare l'elenco e cercarlo.

// 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; 
} 
0

È possibile utilizzare l'enumerazione rapida attraverso l'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; 
} 
+0

non so per certo che questo è più veloce, ma per l'assegnazione finale è possibile utilizzare: maxX = MAX (maxX, newX); ecc ... –

21

In questo caso, è necessario utilizzare -[CPPlotSpace scaleToFitPlots:]. Per calcoli più generali sui valori degli array, continua a leggere ...

Questo è un uso ideale per la codifica Key-Value e associati array operators. Nel tuo esempio,

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]; 

Gli operatori di matrice chiamano valueForKeyPath: sul contentArray che dà una matrice costruita chiamando stesso valueForKeyPath: in ogni membro della matrice con il percorso della chiave a destra dell'operatore matrice (cioè @min e @max). La chiamata orignale applica quindi l'operatore specificato alla matrice risultante. Si potrebbe facilmente definire una categoria sulla NSArray di restituirvi una struttura di valori min/max:

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; 
} 
+0

Grazie Barry, la tua risposta è stata molto utile. Sai se esiste anche una funzione di auto-regolazione per gli assi? – Kevin

+0

La classe 'CPAxis' supporta un criterio di etichettatura automatica (' CPAxisLabelingPolicyAutomatic'). Penso che l'asse occuperà automaticamente lo spazio di trama in modo che sia sufficiente impostare la politica di etichettatura su automatico e quindi dirgli di relabel quando lo spazio trama cambia dimensione. –

+0

@BarryWark Cosa succede se sono presenti 2 o più array diversi nella stessa area del grafico? Come posso prendere il valore Y più piccolo e uno più grande di tutti gli array? –

0

se avete NSMutableArray di NSDictionary oggetti è possibile utilizzare questo:

-(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; 
} 

Si potrebbe accedere ai metodi come questo se in un'altra classe:

GraphData *c=[[GraphData alloc] init]; 
float maxY=[c findMax:plotData arrayKey:[NSNumber numberWithInt:1]]; //1 or 0 depending on axis 
[c release]; 
Problemi correlati