2010-02-26 12 views
10

Chcę uzyskać wartości maksymalne i minimalne obiektu NSMutableArray, aby można było utworzyć obszar wydruku i wykres w oparciu o te wartości maksymalne i minimalne.OBJ-C: Uzyskiwanie wartości minimalnej/maksymalnej w obiekcie NSMutableArray

Mój kod wygląda następująco:

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

Co mam wypełnić puste pola na XRange i yRange przypisania jeśli chcę wykres span tylko przestrzeń, co określono w contentArray?

Odpowiedz

0

Możesz znaleźć wartości maksymalne i minimalne, gdy je wypełniasz, ale będą działać, gdy zostaną użyte w Twoim fragmencie. Jeśli chcesz czegoś bardziej ogólnego, powinieneś po prostu przejrzeć listę i ją wyszukać.

// 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

Możesz użyć szybkiego wyliczenia poprzez macierz. .

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

nie wiem na pewno, że jest to szybsze, ale do ostatecznego przydziału można użyć: Maxx = MAX (maxX, newX); itd ... –

21

W takim przypadku należy użyć -[CPPlotSpace scaleToFitPlots:]. Aby uzyskać bardziej ogólne obliczenia wartości tablic, przeczytaj ...

Jest to idealne rozwiązanie do kodowania kluczem wartości i związane z nim array operators. W przykładzie

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

Operatorzy array zadzwonić valueForKeyPath: na contentArray co daje tablicę zbudowaną przez wywołanie samego valueForKeyPath: na każdym elemencie tablicy z kluczem ścieżki po prawej stronie operatora array (tj @min i @max). Wywołanie orignal następnie stosuje dany operator do wynikowej tablicy. Można łatwo zdefiniować kategorię na NSArray aby oddać struct wartości min-/maks:

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

Dzięki Barry, twoja odpowiedź była bardzo pomocna. Czy wiesz, że istnieje również funkcja automatycznej regulacji osi? – Kevin

+0

Klasa 'CPAxis' obsługuje politykę automatycznego etykietowania (' CPAxisLabelingPolicyAutomatic'). Oś będzie, jak mi się zdaje, automatycznie rozciągać obszar kreślenia, więc wystarczy ustawić politykę etykietowania na automatyczną, a następnie nakazać jej ponowne etykietowanie, gdy obszar wykresu zmieni rozmiar. –

+0

@BarryWark Co się stanie, jeśli mam dwie lub więcej różnych tablic do wydrukowania w tym samym obszarze wykresu? Jak mogę wziąć jedną najmniejszą i jedną największą wartość Y wszystkich tablic? –

0

jeśli masz NSMutableArray z NSDictionary obiektów można użyć to:

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

by uzyskać dostęp do metod tak jakby w innej klasy:

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