Min and Max Value of an NSMutableArray - iphone

I have a simple looking piece of code that has me completely flummoxed.
NSInteger ymax;
NSInteger ymin;
NSInteger numberIndex1;
NSInteger numberIndex2;
for (NSNumber *theNumber in array2)
{
if ([theNumber integerValue] > ymax) {
ymax = [theNumber integerValue];
numberIndex1 = [array2 indexOfObject:theNumber];
}
}
for (NSNumber *theNumber in array2)
{
if ([theNumber integerValue] < ymin) {
ymin = [theNumber integerValue];
numberIndex2 = [array2 indexOfObject:theNumber];
}
}
NSLog(#"Highest number: %d at index: %d", ymax, numberIndex1);
NSLog(#"Lowest number: %d at index: %d", ymin, numberIndex2);
The NSLog is outputted as:
Highest number: 129171656 at index: -1073752392 (Huh??)
Lowest number: 57 at index: 5 (Correct)
How do you explain this odd behaviour? Both the functions look the same. One is working and one isn't? I've played around a lot with this, but I still can't put my finger on it. Any help would be appreciated/

You can get maximum and minimum number as below code. It may help you
NSNumber * max = [array2 valueForKeyPath:#"#max.intValue"];
NSNumber * min = [array2 valueForKeyPath:#"#min.intValue"];
NSUInteger numberIndex1 = [array indexOfObject:min];
NSUInteger numberIndex2 = [array indexOfObject:max];
NSLog(#"Max Value = %d and index = %d",[max intValue],numberIndex1);
NSLog(#"Min Value = %d and index = %d",[min intValue],numberIndex2);

If I am not wrong you are considering the default value of NSInteger is 0, No, it isn't guaranteed to be zero, since it's a local automatic variable. Without initialization, its value is indeterminate.
so you need to set default values for your var, start with ymax = -1;

Please initialize NSInteger ymax = 0;
NSInteger ymin = 0 ;
NSInteger numberIndex1 = 0;
NSInteger numberIndex2 = 0;
It will fix your issue.
Otherwise it is checking with a garbage value and giving wrong result.

enjoy with my answer.......happy coding
NSArray *arr1=[[NSArray 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];
NSNumber * max = [arr1 valueForKeyPath:#"#max.floatValue"];
NSString *str=[NSString stringWithFormat:#"%#",max];
NSInteger path=[arr1 indexOfObject:str];
NSIndexPath *indepath=[NSIndexPath indexPathForItem:path inSection:0];
NSNumber * min = [arr1 valueForKeyPath:#"#min.floatValue"];
NSString *str1=[NSString stringWithFormat:#"%#",min];
NSInteger path1=[arr1 indexOfObject:str1];
NSIndexPath *indepath1=[NSIndexPath indexPathForItem:path1 inSection:0];
NSLog(#"Max Value = %f and index = %ld",[max floatValue],(long)indepath.row);
NSLog(#"Min Value = %f and index = %ld",[min floatValue],(long)indepath1.row);

A more legitimate solution would be:
NSArray *originalArray = #[[NSNumber numberWithInt:91],
[NSNumber numberWithInt:12],
[NSNumber numberWithInt:99123],
[NSNumber numberWithInt:9],
[NSNumber numberWithInt:43234]];
NSArray *sortedArray = [originalArray sortedArrayUsingSelector:#selector(compare:)];
NSNumber *minNumber = [sortedArray objectAtIndex:0];
NSNumber *maxNumber = [sortedArray lastObject];
NSInteger minIndex = [originalArray indexOfObject:minNumber];
NSInteger maxIndex = [originalArray indexOfObject:maxNumber];

Related

How to sort an array with alphanumeric values?

I have an array which contains strings like frame_10#3x.png , frame_5#3x.png,frame_19#3x.png etc.
So I want to sort this array according to the number after the underscore i.e. the correct sequence will be frame_5#3x.png,frame_10#3x.png,frame_19#3x.png.
I tried to use the following method but no result:
NSInteger firstNumSort(id str1, id str2, void *context) {
int num1 = [str1 integerValue];
int num2 = [str2 integerValue];
if (num1 < num2)
return NSOrderedAscending;
else if (num1 > num2)
return NSOrderedDescending;
return NSOrderedSame;
}
Please suggest how to do this sorting for array.
NSArray *sry_img = [[NSArray alloc] initWithObjects:#"frame_18#3x.png",#"frame_17#3x.png",#"frame_1222#3x.png",#"frame_10#3x.png",#"frame_3#3x.png",#"frame_4#3x.png",#"frame_4#3x.png",#"frame_1#3x.png",#"frame_4#3x.png",#"frame_4#3x.png",nil];
NSArray *sortedStrings = [sry_img sortedArrayUsingSelector:#selector(localizedStandardCompare:)];
NSLog(#"%#",sortedStrings);
Enjy .......
But
localizedStandardCompare:, added in 10.6, should be used whenever file names or other strings are presented in lists and tables where Finder-like sorting is appropriate. The exact behavior of this method may be tweaked in future releases, and will be different under different localizations, so clients should not depend on the exact sorting order of the strings.
you want to do something like:
NSArray *components1 = [str1 componentsSeparatedByString:#"_"];
NSArray *components2 = [str2 componentsSeparatedByString:#"_"];
NSString *number1String = [components1 objectAtIndex:([components1 count] - 1])];
NSString *number2String = [components2 objectAtIndex:([components2 count] - 1])];
return [number1String compare:number2String];
I am not sure if my solution is the best possible approach but it can solve your problem for the time being :) .
1) First I have written a function to get the numbers before # character in your string and then I implemented simple SELECTION SORT algo to sort the array using this functions.
- (NSString*)getSubStringForString:(NSString*)value {
// First we will cut the frame_ string
NSMutableString *trimmedString = [NSMutableString stringWithString:[value substringWithRange:NSMakeRange(6, [value length]-6)]];
// New String to contain the numbers
NSMutableString *newString = [[NSMutableString alloc] init];
for (int i = 0; i < [trimmedString length] ; i++) {
NSString *singleChar = [trimmedString substringWithRange:NSMakeRange(i, 1)];
if (![singleChar isEqualToString:#"#"]) {
[newString appendString:singleChar];
} else {
break;
}
}
return newString;
}
This is the selection Implementation of the algo for sorting. The main logic is in the for loop. You can copy the code in viewDidLoad method to test.
NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:#"frame_10#3x.png",#"frame_5#3x.png",
#"frame_3#3x.png", #"frame_19#3x.png",
nil];
NSLog(#"Values before Sort: %#", array);
int iPos;
int iMin;
for (iPos = 0; iPos < [array count]; iPos++)
{
iMin = iPos;
for (int i = iPos+1; i < [array count]; i++)
{
if ([[self getSubStringForString:[array objectAtIndex:i]] intValue] >
[[self getSubStringForString:[array objectAtIndex:iMin]] intValue]) {
iMin = i;
}
}
if ( iMin != iPos )
{
NSString *tempValue = [array objectAtIndex:iPos];
[array replaceObjectAtIndex:iPos withObject:[array objectAtIndex:iMin]];
[array replaceObjectAtIndex:iMin withObject:tempValue];
}
}
NSLog(#"Sorted Values: %#", array);
I hope that it can atleast keep you going. :)
You can try this-
NSString *str1 = [[[[str1 componentsSeparatedByString:#"frame_"] objectAtIndex:1] componentsSeparatedByString:#"#3x.png"] objectAtIndex:0];
int num1 = [str1 integerValue];

Problem comparing two arrays

i have a loop in Objective C and i compare two index of the same array but the comparison doesnt work ,there is no compile error. Variable iMinor is always zero and arrayDistancias is not empty:
NSMutableArray *arrayDistancias = [NSMutableArray array];
NSNumber *lat1 = [NSNumber numberWithFloat:39.0025];
NSNumber *lat2 = [NSNumber numberWithFloat:40.2710];
NSNumber *lat3 = [NSNumber numberWithFloat:38.5316];
NSNumber *lat4 = [NSNumber numberWithFloat:27.4529];
NSNumber *lng1 = [NSNumber numberWithFloat:-1.5139];
NSNumber *lng2 = [NSNumber numberWithFloat:-3.4327];
NSNumber *lng3 = [NSNumber numberWithFloat:-7.0029];
NSNumber *lng4 = [NSNumber numberWithFloat:-15.3432];
//for (NSInteger i = 0; i < 40; i++)
[arrayDistancias addObject:[NSNumber numberWithInteger:[self calcularDistancia:latitudaqui :lat1 :longitudaqui :lng1]]];
[arrayDistancias addObject:[NSNumber numberWithInteger:[self calcularDistancia:latitudaqui :lat2 :longitudaqui :lng2]]];
[arrayDistancias addObject:[NSNumber numberWithInteger:[self calcularDistancia:latitudaqui :lat3 :longitudaqui :lng3]]];
[arrayDistancias addObject:[NSNumber numberWithInteger:[self calcularDistancia:latitudaqui :lat4 :longitudaqui :lng4]]];
int iMinor = 0;
for (int i = 0; i < [arrayDistancias count]; i++) {
if([arrayDistancias objectAtIndex: i] < [arrayDistancias objectAtIndex: iMinor]){
iMinor = i;
}
}
thanks in advance
[arrayDistances objectAtIndex: i] retuns the NSNumber object, not the integer value. In order to get the integer value use intValue method on the returned object. So, you should compare it like this.
if ([[arrayDistances objectAtIndex: i] intValue] <
[[arrayDistances objectAtIndex: iMinor] intValue]) {

How to add array values using NSMutableArray in iPHone?

I have the data into the mutable array and the value of array is,
{ "20", "40", "50","60", "70"}.
I have stored the string values into the array.
Now i want to total value of the array. Result is : 240
Thanks!
NSInteger value = 0;
for (String *digit in myArray) {
value += [digit intValue];
}
int total=0;
for(NSString *currentString in myArray){
total +=[currentString intValue];
}
NSLog(#"Sum:%d",total);
This adds all values:
__block NSInteger sum = 0;
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
sum += [obj intValue];
}];
You can do as follows:
int totalSum = 0;
NSmutableArray *arrayData = [[NSmutableArray alloc] init];
[arrayData addObject:#"20"];
[arrayData addObject:#"40"];
[arrayData addObject:#"50"];
[arrayData addObject:#"60"];
[arrayData addObject:#"70"];
for(int i=0; i<[arrayData count];i++)
{
totalSum = totalSum + [[arrayData objectAtIndex:i] intValue];
}
NSLog(#"Total:%d",totalSum);
Please let me know if you have any question.
How about the most elegant solution using key-value Collection aggregators:
NSNumber *sum = [myArray valueForKeyPath:#"#sum.self"];

How to find the median value of NSNumbers in an NSArray?

I'm trying to calculate the median of a (small) set of NSNumbers in an NSArray. Every object in the NSArray is a NSNumber.
Here is what I'm trying, but it's not working:
NSNumber *median = [smallNSArray valueForKeyPath:#"#median.floatValue"];
NSArray *sorted = [smallNSArray sortedArrayUsingSelector:#selector(compare:)]; // Sort the array by value
NSUInteger middle = [sorted count] / 2; // Find the index of the middle element
NSNumber *median = [sorted objectAtIndex:middle]; // Get the middle element
You can get fancier. For example, the median of a set with an even number of numbers is technically the average of the middle two numbers. You could also wrap this up into a neat one-line method in a category on NSArray:
#interface NSArray (Statistics)
- (id)median;
#end
#implementation NSArray (Statistics)
- (id)median
{
return [[self sortedArrayUsingSelector:#selector(compare:)] objectAtIndex:[self count] / 2];
}
#end
For anyone who has the unusual need for this function, here's a category method on NSArray that will work with both an odd and an even number of elements:
NSARRAY CATEGORY METHOD
- (float)median {
if (self.count == 1) return [self[0] floatValue];
float result = 0;
NSUInteger middle;
NSArray * sorted = [self sortedArrayUsingSelector:#selector(compare:)];
if (self.count % 2 != 0) { //odd number of members
middle = (sorted.count / 2);
result = [[sorted objectAtIndex:middle] floatValue];
}
else {
middle = (sorted.count / 2) - 1;
result = [[#[[sorted objectAtIndex:middle], [sorted objectAtIndex:middle + 1]] valueForKeyPath:#"#avg.self"] floatValue];
}
return result;
}
TEST
NSArray * singleElement = #[#1];
NSArray * oddNumberOfElements = #[#3, #5, #7, #12, #13, #14, #19, #20, #21, #22, #23, #29, #39, #40, #56];
NSArray * evenNumberOfElements = #[#3, #5, #7, #12, #13, #14, #19, #20, #21, #22, #23, #29, #40, #56];
NSLog(
#"oddNumberOfElements: %f, evenNumberOfElements: %f singleElement: %f",
[oddNumberOfElements median], [evenNumberOfElements median], [singleElement median]
);
//oddNumberOfElements: 20.000000, evenNumberOfElements: 19.500000 singleElement: 1.000000
Swift Extension
extension Array where Element: Comparable {
var median: Element {
return self.sort(<)[self.count / 2]
}
}

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

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?
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;
}
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;
}
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;
}
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];
//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);
}