concatenate all values in NSMutableDictionary cast to int, NSInteger and NSString - objective-c

so I have a couple NSMutableDictionarys and each key/valeu pair for a specific dictionary hold either a string or integer value. I would like to know if there is a way to iterate through the dictionary and concatenate the values. In PHP I could do something like this using an array
// either the dictionary holds all integers or all string values
$integer_array = array( 'a' => 2, 'b' => 9, 'c' => 2, 'd' => 0, 'e' => 1 );
foreach( $integer_array as $key => $value ) {
$concatenated_value .= $value;
}
// cast to int
$concatenated_value = ( int ) $concatenated_value;
// prints: 29201
echo $concatenated_value;
I could also use the implode() as well
$concatenated_value = ( int )(implode("", $integer_array));
// prints: 29201
echo $concatenated_value;
is there something like this for iOS Objective-C?

I don't believe there is a predefined function for it. To me, this doesn't seem like a very common thing to do (is it common in PHP?). I suppose the code would look like this in theory:
int finalVal = 0;
for (NSString *key in keyArray)
{
//If it is variable between NSString and NSNumber as you say, you will
//need to do type checking here.
NSNumber *numVal = [dictionary objectForKey:key];
int num = [numVal intValue];
//----Don't need this part if all values are single digits
while(num > 10)
{
finalVal += num;
finalVal *= 10;
num /= 10;
}
//--------------------------------------------------------
finalVal += num;
finalVal *= 10;
}
finalVal /= 10;
However, this is very unlikely to produce the results you want since dictionaries are not ordered. I think you need a different data structure or an array holding the keys in the order you inserted them (but at that point you might as well just use an array).
EDIT Since you are using an ordered array of keys, I edited the answer above.

Here is how you can do it (it's quite a bit longer, due to the fact that dictionaries in cocoa are not ordered).
NSMutableDictionary *d = [NSMutableDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:1], #"a",
[NSNumber numberWithInt:2], #"b",
[NSNumber numberWithInt:34], #"c",
[NSNumber numberWithInt:56], #"d",nil];
NSArray *sortedKeys = [[d allKeys] sortedArrayUsingSelector: #selector(compare:)];
NSMutableString *res = [NSMutableString string];
[sortedKeys enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
[res appendFormat:#"%d", [[d objectForKey:obj] intValue]];
}];
NSLog(#"%#", res);
This prints 123456

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

Compare two items in one NSArray

I have an array containing twenty items. I want to search through the array, comparing one item to the next one in the array, and then print the larger item. I have already sorted the array. I just want to compare the two items, check what the remainder is between the two values, and if it's greater than say, four, print the larger item.
NSArray* arr = [NSArray arrayWithObjects:
[NSNumber numberWithInt:1],
[NSNumber numberWithInt:6],
[NSNumber numberWithInt:7],
[NSNumber numberWithInt:11],
nil
];
int len = [arr count];
for (int i=0; i < len-1; ++i) {
int num1 = [[arr objectAtIndex:i] intValue];
int num2 = [[arr objectAtIndex:i+1] intValue];
if ( num2-num1 > 4 ) {
NSLog(#"%d", num2);
}
}
--output:--
6
NSEnumerator *itemEnumerator = [theArray objectEnumerator];
YourClass *lastObject = [itemEnumerator nextObject];
YourClass *compareObject;
while( (compareObject = [itemEnumerator nextObject]) != nil)
{
if( /* place your condition here */ )
{
NSLog( … );
}
lastObject = compareObject;
}
Typped in Safari

Objective C - Array With Numbers

Is there a nicer way to fill an array with numbers than what I use?
It's crazy how much I got to write just to fill an array with numbers so they can be used for a calculation in a loop. This is easier in other C based languages like PHP, As3, or Java.
NSArray *myArray = [NSArray arrayWithObjects:
[NSNumber numberWithInt:1000],[NSNumber numberWithInt:237], [NSNumber numberWithInt:2673], nil];
int total = 0;
for(int i = 0; i < [myArray count]; i += 1 ){
total += [[myArray objectAtIndex: i]intValue];
NSLog(#"%i", total);
}
Hopefully there is a shorter way... I just want to fill an array with ints... cant be that hard
I guess you have to use NSNumber for an NSArray. If you want to use ints I guess you'd have to use a c array:
NSInteger myArray[20];
for (int i=0;i<20;i++) {
int num=myArray[i];
//do something
}
NSNumber though is I guess the better approach for this language.
At least you can do fast enumeration to shorten code a bit:
for (NSNumber *n in myArray) {
int num = [n intValue];
//do something....
}
EDIT:
The question has been asked 3 years ago. There have been new literals established to make it easier to create objects like NSNumbers or NSArrays:
NSNumber *n = #100;
or
NSArray *array = #[#100,#50,#10];
Nice short alternative for looping specific integers:
NSArray *numbers = [#"1000,237,2673" componentsSeparatedByString:#","];
for (NSString *i in numbers) {
[i intValue]; // Do something.
}
First start with a C array:
NSInteger myCArray = { 1000, 237, 2673 };
// calculate number of elements
NSUInteger myCArrayLength = sizeof(myCArray) / sizeof(NSInteger;
Second, if you need an NSArray loop through this array and create one:
NSMutableArray *myNSArray = [NSMutableArray arrayWithCapacity:myCArrayLength];
for(NSUInteger ix = 0; ix < myCArrayLength; ix++)
[myNSArray addObject:[NSNumber numberWithInteger:myCArray[ix]];
You can wrap the second piece of code up as a category on NSArray if you're doing it a lot.
too late. but u can do the following too.
int total = 0;
nsarray *myArray = #[#1.8,#100,#299.8];
for(nsnumber *num in myArray){
total+=num;
}

how to add int value from array to NSNumber?

Here is my code
I'm looping through the array and adding to the NSNumber.
NSNumber *totalValue = 0;
NSMutableArray *items = [10, 35, 25]; // Just for demo
for (int i=0; i < items.count; i++)
{
totalValue = totalValue + [items objectAtIndex:i] // How do I add the totalValue?
}
Can someone help me with this code?
NSNumber is an Objective-C class. Unlike in C++, operators cannot be overloaded in Objective-C so you have to call everything manually.
NSNumber *totalValue = [NSNumber numberWithInt:0];
for(…) {
totalValue = [NSNumber numberWithInt:[totalValue intValue] + [[items objectAtIndex:i] intValue]];
}
You might want to use NSInteger instead, which is faster (especially for a large number of items: memory allocation is expensive):
NSInteger totalValueInteger = 0; // no pointer, NSInteger is a POD!
for (…) {
totalValueInteger += [[items objectAtIndex:i] integerValue];
}
NSNumber *totalValue = [NSNumber numberWithInteger:totalValueInteger];
You should really only use NSNumber when you need an Objective-C object, like in an array, dictionary or coder. Otherwise, use a POD like NSInteger, int or double.
First of all, you can probably do this entire thing using KVC:
NSNumber *total = [items valueForKeyPath:#"#sum.integerValue"];
But to answer your original question, NSNumber is immutable which means you can't change it or increment its value. Creating a new NSNumber on each iteration of your loop is inefficient and wasteful.
You should use a standard int or NSInteger to sum up the total, and then convert the resulting value to an NSNumber at the end if you need it like that.
Might as well make the intermediate an int.
int temp = 0;
for(…) {
temp += [[items objectAtIndex:i] intValue];
}
NSNumber *totalValue = [NSNumber numberWithInt:temp];

Reading random values from an array

I have an array with a 14 strings. I want to display each of these 14 strings to the user without duplicates. The closest I got was creating an array of integers and shuffling their values, and then reading from the array of strings using one of the numbers from the int array as the index:
//appDelegate.randomRiddles is an array of integers that has integer values randomly
appDelegate.randomRiddlesCounter++;
NSNumber *index=[appDelegate.randomRiddles objectAtIndex:appDelegate.randomRiddlesCounter];
int i = [index intValue];
while(i>[appDelegate.currentRiddlesContent count]){
appDelegate.randomRiddlesCounter++;
index=[appDelegate.randomRiddles objectAtIndex:appDelegate.randomRiddlesCounter];
i = [index intValue];
}
hintText.text = [[appDelegate.currentRiddlesContent objectAtIndex:i] objectForKey:#"hint"];
questionText.text = [[appDelegate.currentRiddlesContent objectAtIndex:i] objectForKey:#"question"];
But my way is causing crashing and duplicates. Oh and each time I read a value from the strings array, that string is removed from the array making its count decrease by 1. So that complicates this a little bit.
Get the elements in your array like this:
int position = arc4random() % ([myArray count]);
This way even though count decreases by one, that is ok, as you will still get a valid next position value till there aren't any more posible values.
By "without duplicates" I assume you mean that you want to use each string in the array once before you use the same string again, not that you want to filter the array so it doesn't contain duplicate strings.
Here's a function that uses a Fisher-Yates shuffle:
/** #brief Takes an array and produces a shuffled array.
*
* The new array will contain retained references to
* the objects in the original array
*
* #param original The array containing the objects to shuffle.
* #return A new, autoreleased array with all of the objects of
* the original array but in a random order.
*/
NSArray *shuffledArrayFromArray(NSArray *original) {
NSMutableArray *shuffled = [NSMutableArray array];
NSUInteger count = [original count];
if (count > 0) {
[shuffled addObject:[original objectAtIndex:0]];
NSUInteger j;
for (NSUInteger i = 1; i < count; ++i) {
j = arc4random() % i; // simple but may have a modulo bias
[shuffled addObject:[shuffled objectAtIndex:j]];
[shuffled replaceObjectAtIndex:j
withObject:[original objectAtIndex:i]];
}
}
return shuffled; // still autoreleased
}
If you want to keep the relationship between the riddles, hints, and questions then I'd recommend using a NSDictionary to store each set of related strings rather than storing them in separate arrays.
This task is very easy using an NSMutableArray. In order to do this, simply remove a random element from the array, display it to the user.
Declare a mutable array as an instance variable
NSMutableArray * questions;
When the app launches, populate with values from myArray
questions = [[NSMutableArray alloc] initWithArray:myArray]];
Then, to get a random element from the array and remove it, do this:
int randomIndex = (arc4random() % [questions count]);
NSDictionary * anObj = [[[questions objectAtIndex:randomIndex] retain] autorelease];
[questions removeObjectAtIndex:randomIndex];
// do something with element
hintText.text = [anObj objectForKey:#"hint"];
questionText.text = [anObj objectForKey:#"question"];
No need to type that much. To shuffle an array, you just sort it with random comparator:
#include <stdlib.h>
NSInteger shuffleCmp(id a, id b, void* c)
{
return (arc4random() & 1) ? NSOrderedAscending : NSOrderedDescending;
}
NSArray* shuffled = [original sortedArrayUsingFunction:shuffleCmp context:0];
You could copy the array into an NSMutableArray and shuffle that. A simple demonstration of how to shuffle an array:
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// Original array, here initialised with 1..9
NSArray *arr = [NSArray arrayWithObjects:
[NSNumber numberWithInt: 1],
[NSNumber numberWithInt: 2],
[NSNumber numberWithInt: 3],
[NSNumber numberWithInt: 4],
[NSNumber numberWithInt: 5],
[NSNumber numberWithInt: 6],
[NSNumber numberWithInt: 7],
[NSNumber numberWithInt: 8],
[NSNumber numberWithInt: 9],
nil];
// Array that will be shuffled
NSMutableArray *shuffled = [NSMutableArray arrayWithArray: arr];
// Shuffle array
for (NSUInteger i = shuffled.count - 1; i > 0; i--)
{
NSUInteger index = rand() % i;
NSNumber *temp = [shuffled objectAtIndex: index];
[shuffled removeObjectAtIndex: index];
NSNumber *top = [shuffled lastObject];
[shuffled removeLastObject];
[shuffled insertObject: top atIndex: index];
[shuffled addObject: temp];
}
// Display shuffled array
for (NSNumber *num in shuffled)
{
NSLog(#"%#", num);
}
[pool drain];
return 0;
}
Note that all arrays and numbers here are autoreleased, but in your code you might have to take care of memory management.
If you don't have to keep the elements in the array, you can simplify that (see Oscar Gomez' answer too):
NSUInteger index = rand() % shuffled.count;
NSLog(#"%#", [shuffled objectAtIndex: index]);
[shuffled removeObjectAtIndex: index];
At the end, shuffled will be empty. You will have to change the loop conditions too:
for (NSUInteger i = 0; i < shuffled.count; i++)