valueForKeyPath: #"#max.self" not work when number is 100 - objective-c

NSArray *vals = {100,100,50,50,50}
maximumValue = [[vals valueForKeyPath: #"#max.self"] intValue];
Returns
maximumValue : 50

You probably have an array of strings. When compared as strings, "50" is greater than "100" because 5 comes after 1. You need to convert to integers first, then take the max.
Unfortunately, ObjC doesn't have the map function, so you need to do it manually.
NSMutableArray *intArray = [NSMutableArray array];
for (NSString *val in vals) {
[intArray addObject:#(val intValue)];
}
maximumValue = [[intArray valueForKeyPath: #"#max.self"] intValue];
Edit
Based on Sulthan's suggestion, you can also do the following:
NSArray *a = #[ #"50", #"100" ];
NSLog(#"%#", [[a valueForKeyPath:#"intValue"] valueForKeyPath:#"#max.self"]);
The first call to valueForKeyPath:#"intValue" gives an array of NSNumbers. At this point, the #max.self key-path gives the expected value, as a numeric comparison is made between elements.

NSArray *vals = #[#100,#100,#50,#50,#50];
NSLog(#"%d",[[vals valueForKeyPath: #"#max.self"] intValue]

Related

How To Compare Integer to Objective-C enum

- (void)updateCheckBoxes {
NSArray *availableFuncUnits = _scanner.availableFunctionalUnitTypes;
for(int i = 0; i < [availableFuncUnits count]; i++) {
}
}
If I put a breakpoint inside the for loop, the elements of the NSArray * 'availableFuncUnits' are (__NSCFNumber *)(int)0 and (__NSCFNumber *)(long)3.
The array is supposed to contain elements of the following :
enum
{
ICScannerFunctionalUnitTypeFlatbed = 0,
ICScannerFunctionalUnitTypePositiveTransparency = 1,
ICScannerFunctionalUnitTypeNegativeTransparency = 2,
ICScannerFunctionalUnitTypeDocumentFeeder = 3
};
typedef NSUInteger ICScannerFunctionalUnitType;
Shouldn't I be able to do the following?
if([availableFuncUnits objectAtIndex:i] == ICScannerFunctionalUnitType.ICScannerFunctionalUnitTypeDocumentFeeder) {}
But it always gives me an error saying 'Expected identifier or '('.
How can I perform this comparison correctly? Thanks a lot for the help!
There are two problems that I see:
1) The array availableFuncUnits contains NSNumber objects. You cant directly compare them with primitive types (NSUInteger).
So your if should be like this:
ICScannerFunctionalUnitType type = [availableFuncUnits[i] integerValue]
if(type == ICScannerFunctionalUnitTypeDocumentFeeder){}
In your snippet you were comparing the pointer, not the object.
2) The error you were seeing is because the proper way to use enums is:
i = ICScannerFunctionalUnitTypeDocumentFeeder
You can't store integers in an NSArray because array's can only contain objects. To get integers into an array they must be wrapped with NSNumber:
NSInteger a = 100;
NSInteger b = 200;
NSInteger c = 300;
// Creating NSNumber objects the long way
NSArray *arrayOne = [NSArray alloc] initWithObjects:[NSNumber numberWithInteger:a],
[NSNumber numberWithInteger:b],
[NSNumber numberWithInteger:c], nil];
// Creating NSNumber objects the short way
NSArray *arrayTwo = [[NSArray alloc] initWithObjects:#100, #200, #300, nil];
This is relevant you your question because when you extract your NSNumber objects from your array, if you want to then compare them to actual integers, you must convert them back to integers (unwrap them).
NSLog(#"%d", [arrayOne firstObject] == 100); // COMPILER WARNING!!!
NSLog(#"%d", [[arrayOne firstObject] integerValue] == 100); // True
NSLog(#"%d", [[arrayTwo lastObject] integerValue] == 200); // False
This stage appears to be missing in your example.
Finally to compare your integer values with those from an enum, there's no need to reference the enum name, just use the individual values that make up the enum:
[[arrayTwo lastObject] integerValue] == ICScannerFunctionalUnitTypeFlatbed

How to change an array of strings into an array of integers in objC?

I retrieved an array of NSString-Objects (couples) out of another dynamic array valuesFirstdance. I know that the strings always contain integers. I need the values to be of type integer to sort the couplesarray. How would I change to type of every array value?
Thanks
couples = [valuesFirstdance allKeys];
NSArray* couples2 = [couples sortedArrayUsingSelector:#selector(intValue)];
To answer the question directly:
NSMutableArray *integerArray = [[NSMutableArray alloc] initWithCapacity:couples.count];
for (NSString *s in couples) {
[integerArray addObject:[NSNumber numberWithInteger:s.integerValue]];
}
But you could also do numeric sorting on the string values, e.g., using NSNumericSearch:
NSArray *sortedArray = [couples sortedArrayUsingComparator:^(NSString *o1, NSString *o2) {
return [o1 compare:o2 options:NSNumericSearch];
}];
NSString has a method called intValue - that is what you're looking for.
Of course, a better solution would be to have an array of NSNumbers instead of NSStrings.
You don't have to change the type of every array value to sort the couples array - look at this:
NSArray *sortedArray = [couplesArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSString *firstString = (NSString*) obj1;
NSString *secondString = (NSString*) obj2;
if([firsString integerValue]<[secondString integerValue])
return (NSComparisonResult) NSOrderedDescending;
else if([firsString integerValue]>[secondString integerValue])
return (NSComparisonResult) NSOrderedAscending;
return (NSComparisonResult) NSOrderedSame;
}];

obj-c fetching strings from array

i'm new to obj-c (this is my first day class eheh) and i'm trying to change a label with a random string from a multidimensional array. plus, every time the button is hitten you switch the array. i know it's a bit odd eheh… this is the IBAction:
UIButton *button = (UIButton *)sender;
NSMutableArray *firstArray = [NSMutableArray array];
[firstArray addObject:#"foo"];
NSMutableArray *secondArray = [NSMutableArray array];
[secondArray addObject:#"bar"];
NSMutableArray *frasi = [NSMutableArray array];
[frasi addObject:firstArray];
[frasi addObject:secondArray];
NSMutableArray *array = [NSMutableArray arrayWithObjects:[frasi objectAtIndex:[button isSelected]], nil];
NSString *q = [array objectAtIndex: (arc4random()% [array count] )];
NSString *lab = [NSString stringWithFormat:#"%#", q];
self.label.text = lab;
all works, but the new label is
( "foo" )
instead of just foo (without quotes)... probably i mess in the last block of code...
ty
So, you create 2 mutable arrays, then add them to a new mutable array frasi. Then you get one of those two arrays and use it as the single element (because you use arrayWithObjects: instead of arrayWithArray:) of a new array array.
So array is an array that contains a single array element (instead of an array of strings as you may believe).
When you get an object from array, it's always the same single object that was used to initialize it: either firstArray or secondArray.
So you get an array of strings where you expect a string. When using stringWithFormat:, the specifier %# is replaced with the string description of that object.
A string returns itself as its own description. But the description of an array is the list of all its elements separated with commas and surrounded by parenthesis, which is why you get ( "foo" ).
So instead or creating unneeded arrays, you may just replace all the 8th last lines with this:
NSArray *array = [button isSelected] ? secondArray : firstArray;
self.label.text = [array objectAtIndex:arc4_uniform([array count])];
Actually u have array within array
Replace this line with yours:
NSString *q = [[array objectAtIndex: (arc4random()% [array count] )] objectAtIndex:0];

Add up all values from NSMutableArray

I have a NSMutableArray, containing x different NSStrings (NSString but only numbers no letters). I would like to add up all of the values to return a single float, or int. I think I have to do this with a for loop, but i am very unfamiliar with for loops....
OK I have reached this point:
for (NSString *a in det)
{
float x = [a floatValue];
NSLog(#"%.2f",x);
}
And this returns all the values like this in ´NSLog`:
23.00
8.00
61.00
...
How could i just add them up now?
You can avoid looping and instead use the key value coding and obtain the total
NSMutableArray *arr = [NSMutableArray arrayWithObjects:#"1.1", #"2.2", #"3.1", nil];
NSNumber *sum = [arr valueForKeyPath:#"#sum.floatValue"];
Variable sum will be 6.4.
Try this:
float total = 0;
for(NSString *str in det)
{
total += [str floatValue];
}
Here is the code for a for-in if you want to save a bit of typing. It's preferable to use fast enumeration for these types of scenarios with data structures that support it.
float result = 0.0;
for(NSString *i in nsArray)
{
result += [i floatValue];
}
int result = 0;
for(int i=0;i<[array count];i++)
result += [[array objectAtIndex:i] intValue];
if you need to return a float simply define result as float and use floatValue instead of intValue

How to assign integer from NSMutableArray

I would like to assign NSInteger by using NSMutableArray is there any way to solve this?
It is not working on simulator and cut off when run the application.
NSInteger Section;
NSMutableArray dataSourceSection;
Section = (NSInteger)[dataSourceSection objectAtIndex:2];
Thank you.
A NSMutableArray only stores objects. NSInteger is not an object, but a primitive data type. There is a class NSNumber, however, that can be used instead to store numeric values inside objects. Here's one example.
NSNumber *five = [NSNumber numberWithInteger:5];
NSMutableArray *numbers = [NSMutableArray array];
[numbers addObject:five];
To get the object back and retrieve the integer value use,
NSNumber *firstNumber = [numbers objectAtIndex:0];
NSInteger valueOfFirstNumber = [firstNumber integerValue];
you can't pull an NSInteger out of an NSMutableArray, basically because you can't put anything rather than objects in. in your case NSNumber would be the way to put numbers in NSMutablearray. if you do so you can easily get hold of your object, which is an NSNumber, and convert it to a NSInteger by:
NSMutableArray *array = [[NSMutableArray alloc] init];
// populate the array with NSNumbers
NSInteger number = [[array objectAtIndex:2] intValue];