How to find the smallest and biggest object of an NSMutableArray - ios

Hi I am trying to make it so that I can find and log the biggest object of an NSMutableArray. I have searched for this, but I have only seen it for an NSArray. This is the code I saw.
numbers = [numbers sortedArrayUsingSelector:#selector(compare:)];
float min = [numbers[0] floatValue]
float max = [[numbers lastObject] floatValue];
However, when I put that in, it doesn't work because I am using a mutable array.
Thanks!

It works for mutable array.
NSArray *sortedNumbers = [numbers sortedArrayUsingSelector:#selector(compare:)];
float min = [sortedNumbers[0] floatValue]
float max = [[sortedNumbers lastObject] floatValue];

Related

Array items showing error in IOS

I have an array with some items to rotate the image view when button is clicked, now when I pass the array with getting current index it showing an error, I'm confused why I'm getting this.
My code is this:
- (IBAction)my:(id)sender {
NSString *cureentIndex=0;
NSArray *persons = [NSArray arrayWithObjects:#"M_PI",#" M_PI_4",#" M_PI_2",#"M_PI*2", nil];
NSArray *person = #[#"M_PI", #"M_PI_4", #"M_PI_2"];
_imageView.transform = CGAffineTransformMakeRotation(person[cureentIndex])
if currentIndex != persons.count-1 {
currentIndex = currentIndex + 1
}else {
// reset the current index back to zero
currentIndex = 0
}
}
The error is here:
You have declared cureentIndex as NSString *, so when you say person[cureentIndex] the compiler thinks that person must be a dictionary, since you are using the [] access with an object. This causes the error since person is actually an array and it cannot be indexed with a string.
I think you meant to declare cureentIndex as int, or perhaps you meant to say currentIndex?
There are a lot of issues, please try this
NSInteger currentIndex = 0;
NSArray<NSNumber *> *persons = #[#(M_PI), #(M_PI_4), #(M_PI_2)];
- (IBAction)my:(id)sender {
_imageView.transform = CGAffineTransformMakeRotation(persons[currentIndex].doubleValue)
currentIndex = (currentIndex + 1) % persons.count;
}
There are some errors:
The index must be an int
NSString *cureentIndex=0;
becomes
int currentIndex = 0;
and the array must be of double not string, CGAffineTransformMakeRotation requires a CGFloat that is a double
NSArray *person = #[#"M_PI", #"M_PI_4", #"M_PI_2"];
becomes
NSArray *person = #[[NSNumber numberWithDouble:M_PI], [NSNumber numberWithDouble:M_PI_4], [NSNumber numberWithDouble:M_PI_2]];
and
_imageView.transform = CGAffineTransformMakeRotation(person[cureentIndex])
becomes
_imageView.transform = CGAffineTransformMakeRotation([person[cureentIndex] doubleValue]);
I don't know why you set currentIndex's property to NSString, In fact we always set the XXXindex(current/last/next) to int or NSInteger property.
Another, the person is an array, it's key must be an int!, it's
value could be any object.
I fix your code to this:
NSInteger currentIndex = 0;
NSArray *person = #[#"M_PI", #"M_PI_4", #"M_PI_2"];
CGFloat rotate = [person[currentIndex] floatValue];
_imageView.transform = CGAffineTransformMakeRotation(rotate);
you will find it did't work well, the ratate will be 0! Because, the NSString's method floatValue or doubleValue can only change string(like: #"123" #"0.5") to a number, the string(like: #"M_PI") can't be change to a right number.
I fix your code to this again:
NSInteger currentIndex = 0;
CGFloat mPi = M_PI;
NSArray *person = #[#(mPi), #(mPi / 4.0), #(mPi / 2.0)];
CGFloat rotate = [person[currentIndex] floatValue];
_imageView.transform = CGAffineTransformMakeRotation(rotate);
The Code works well! This is because M_PI is A Macro, if you
write code #"M_PI", the system can't recognize its value 3.1415926. So
your must write M_PI instead of #"M_PI".
In fact, this problem's core is you need a number, so your array must include some numbers! Or some string just like number! :)

Get maximum value from NSMutableArray [duplicate]

This question already has answers here:
Getting Max Date from NSArray, KVC
(2 answers)
Closed 8 years ago.
How can I get a maximum value from an NSMutableArray. Values are stores as NSString in array as below
for(int counter=0; counter<[datesArray count];counter++)
{
glass = [NSString stringWithFormat:#"%f",[[dbhandler todayData:currentDate] floatValue]];
[graphGlassesArray addObject:glass];
}
Array name is graphGlassesArray.
You can get the max value from an array using:
NSNumber* max = [graphGlassesArray valueForKeyPath:#"max.self"];
float maxFloat = [max floatValue]
You should also try to use Key Value Coding (https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/KeyValueCoding/Articles/CollectionOperators.html). To obrain the max in a NSArray you can do [array valueForKeyPath:#"#max.attribute"]. Try to look at this link http://nshipster.com/kvc-collection-operators/.
float max = 0.f;
for(int counter=0; counter<[datesArray count];counter++)
{
glass = [NSString stringWithFormat:#"%f",[[dbhandler todayData:currentDate] floatValue]];
[graphGlassesArray addObject:glass];
if(max < [[dbhandler todayData:currentDate] floatValue]) {
max = [[dbhandler todayData:currentDate] floatValue];
}
}
Try with this
Try by sorting the mutable array
NSSortDescriptor *desc = [[NSSortDescriptor alloc] initWithKey:nil ascending:NO selector:#selector(localizedCompare:)];
NSString *maxValue = [[graphGlassesArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:desc]] objectAtIndex:0];
[desc release];

Inputted values from textfield to NSArray

I have a problem creating a solution to this problem:
Create an app that will store 5 numbers (preferrably float) and then sort them out.The array type is immutable.
First off: My problem is how to get the floats from the textfield then put it into a array. My idea is to code it like this:
int a = [num1.text intValue];
int b = [num2.text intValue];
int c = [num3.text intValue];
NSArray *myArray;
myArray = [NSArray stringWithFormat: #"%f",a,b,c];
My second problem is that I can't understand how to sort the floats. Will you please give me some idea?
Thank you very much!
Something like this should work:
CGFloat a = [num1Label.text floatValue];
CGFloat b = [num2Label.text floatValue];
CGFloat c = [num3Label.text floatValue];
CGFloat d = [num4Label.text floatValue];
CGFloat e = [num5Label.text floatValue];
NSArray *array = #[ [NSNumber numberWithFloat:a],
[NSNumber numberWithFloat:b],
[NSNumber numberWithFloat:c],
[NSNumber numberWithFloat:d],
[NSNumber numberWithFloat:e]];
array = [array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
// logic for sorting
NSNumber *number1 = (NSNumber *)obj1;
NSNumber *number2 = (NSNumber*)obj2;
return [first compare:second];
}];
CGFloat is basically the same as float.
If you check the Documentation (OPTION + Click on that), you see this:
# define CGFLOAT_TYPE float
// ...
typedef CGFLOAT_TYPE CGFloat;
CG comes from Core Graphics.
float comes from C/C++
It is more recommended to use CGFloat in Objective-C, instead of simply float. Also, NSInteger instead of int.

iOS Accessing Dictionary

I have a plist which looks like this. I usually access using the following lines of code:
NSMutableDictionary *plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:plistPath];
CGFloat redFloat = (CGFloat)[[plistDict objectForKey:#"red"] floatValue];
However as it is nested - how do I access the colour red in BackgroundColour?
Thanks.
Absolutely: reading plist into a dictionary gives you a dictionary of dictionaries, so you need to access BackgroundColour first:
CGFloat redFloat = (CGFloat)[[[plistDict objectForKey:#"BackgroundColour"] objectForKey:#"red"] floatValue];
New syntax lets you write it with fewer characters:
CGFloat redFloat = (CGFloat)[plistDict[#"BackgroundColour"][#"red"] floatValue];
You can use valueForKeyPath: to shortcut too:
CGFloat redFloat = (CGFloat)[[plistDict valueForKeyPath:#"BackgroundColour.red"] floatValue];
CGFloat redFloat = [[[plistDict objectForKey:#"BackgroundColour"] objectForKey:#"red"] floatValue];

Finding smallest and biggest value in NSArray of NSNumbers

What's an effective and great way to compare all the values of NSArray that contains NSNumbers from floats to find the biggest one and the smallest one?
Any ideas how to do this nice and quick in Objective-C?
If execution speed (not programming speed) is important, then an explicit loop is the fastest. I made the following tests with an array of 1000000 random numbers:
Version 1: sort the array:
NSArray *sorted1 = [numbers sortedArrayUsingSelector:#selector(compare:)];
// 1.585 seconds
Version 2: Key-value coding, using "doubleValue":
NSNumber *max=[numbers valueForKeyPath:#"#max.doubleValue"];
NSNumber *min=[numbers valueForKeyPath:#"#min.doubleValue"];
// 0.778 seconds
Version 3: Key-value coding, using "self":
NSNumber *max=[numbers valueForKeyPath:#"#max.self"];
NSNumber *min=[numbers valueForKeyPath:#"#min.self"];
// 0.390 seconds
Version 4: Explicit loop:
float xmax = -MAXFLOAT;
float xmin = MAXFLOAT;
for (NSNumber *num in numbers) {
float x = num.floatValue;
if (x < xmin) xmin = x;
if (x > xmax) xmax = x;
}
// 0.019 seconds
Version 5: Block enumeration:
__block float xmax = -MAXFLOAT;
__block float xmin = MAXFLOAT;
[numbers enumerateObjectsUsingBlock:^(NSNumber *num, NSUInteger idx, BOOL *stop) {
float x = num.floatValue;
if (x < xmin) xmin = x;
if (x > xmax) xmax = x;
}];
// 0.024 seconds
The test program creates an array of 1000000 random numbers and then applies all sorting
techniques to the same array. The timings above are the output of one run, but I make about 20 runs with very similar results in each run. I also changed the order in which the 5 sorting methods are applied to exclude caching effects.
Update: I have now created a (hopefully) better test program. The full source code is here: https://gist.github.com/anonymous/5356982. The average times for sorting an
array of 1000000 random numbers are (in seconds, on an 3.1 GHz Core i5 iMac, release compile):
Sorting 1.404
KVO1 1.087
KVO2 0.367
Fast enum 0.017
Block enum 0.021
Update 2: As one can see, fast enumeration is faster than block enumeration (which is also stated here: http://blog.bignerdranch.com/2337-incremental-arrayification/).
EDIT: The following is completely wrong, because I forgot to initialize the object used as lock, as Hot Licks correctly noticed, so that no synchronization is done at all.
And with lock = [[NSObject alloc] init]; the concurrent enumeration is so slow
that I dare not to show the result. Perhaps a faster synchronization mechanism might
help ...)
This changes dramatically if you add the NSEnumerationConcurrent option to the
block enumeration:
__block float xmax = -MAXFLOAT;
__block float xmin = MAXFLOAT;
id lock;
[numbers enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(NSNumber *num, NSUInteger idx, BOOL *stop) {
float x = num.floatValue;
#synchronized(lock) {
if (x < xmin) xmin = x;
if (x > xmax) xmax = x;
}
}];
The timing here is
Concurrent enum 0.009
so it is about twice as fast as fast enumeration. The result is probably not representative
because it depends on the number of threads available. But interesting anyway! Note that I
have used the "easiest-to-use" synchronization method, which might not be the fastest.
Save float by wrapping under NSNumber then
NSNumber *max=[numberArray valueForKeyPath:#"#max.doubleValue"];
NSNumber *min=[numberArray valueForKeyPath:#"#min.doubleValue"];
*Not compiled and checked, already checked with intValue, not sure about double or float
sort it. take the first and the last element.
btw: you cant store floats in an NSArray, you will need to wrap them in NSNumber objects.
NSArray *numbers = #[#2.1, #8.1, #5.0, #.3];
numbers = [numbers sortedArrayUsingSelector:#selector(compare:)];
float min = [numbers[0] floatValue];
float max = [[numbers lastObject] floatValue];
I agree with sorting the array then picking the first and last elements, but I find this solution more elegant (this will also work for non numeric objects by changing the comparison inside the block):
NSArray *unsortedArray = #[#(3), #(5), #(1)];
NSArray *sortedArray = [unsortedArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSNumber *item1 = (NSNumber *)obj1;
NSNumber *item2 = (NSNumber *)obj2;
return [item1 compare:item2];
}];
If you really want to get fancy and have a really long list and you don't want to block your main thread, this should work:
NSComparator comparison = ^NSComparisonResult(id obj1, id obj2) {
NSNumber *item1 = (NSNumber *)obj1;
NSNumber *item2 = (NSNumber *)obj2;
return [item1 compare:item2];
};
void(^asychSort)(void) = ^
{
NSArray *sortedArray = [unsortedArray sortedArrayUsingComparator:comparison];
dispatch_sync(dispatch_get_main_queue(), ^{
NSLog(#"Finished Sorting");
//do your callback here
});
};
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), asychSort);
Made simple
NSArray *numbers = #[#2.1, #8.1, #5.0, #.3];
numbers = [numbers sortedArrayUsingSelector:#selector(compare:)];
float min = [numbers[0] floatValue];
float max = [[numbers lastObject] floatValue];
NSLog(#"MIN%f",min);
NSLog(#"MAX%f",max);

Resources