Ask about int array in Objective-C - iphone

Code below is a simple c# function return an int array.
I would like to know how to convert it to Objective-C
private int[] test()
{
int[] a = new int[2];
a[0] = 1;
a[1] = 2;
return a;
}

The following code should work:
- (NSArray *)test {
NSArray *a = [NSArray arrayWithObjects:[NSNumber numberWithInt:1], [NSNumber numberWithInt:2], nil];
return a;
}
Note that if we created the NSArray using [[NSArray alloc] initWithObjects:blah, blah, nil];, we'd have to explicitly autorelease the array before returning it in order to avoid a memory leak. In this case, however, the NSArray is created using a convenience constructor, so the array is already autoreleased for us.
Second Question:
Try this:
- (NSMutableArray *)test:(int)count {
NSMutableArray *a = [[NSMutableArray alloc] init];
for (int i = 0; i < count; i++) {
[a insertObject:[NSNumber numberWithInt:0] atIndex:i];
}
return [a autorelease];
}

A bit dummy example:
- (NSArray*) test{
return [NSArray arrayWithObjects:[NSNumber numberWithInt:1], [NSNumber numberWithInt:2], nil];
}
Some notes:
NSArray is a immutable type - so if you want to add/remove values you should use NSMutableArray instead
You can store only objects in NSArray so you need to wrap them into NSNumber (or another obj-c type)
Obj-c is a superset of C so you can freely use c-arrays in you obj-c code if you want

Or an alternative path would be to use normal c code (is allowed in objective c):
int a[2]={1, 2};
Or in a function:
int *somefunc(void){
static int a[2]={1, 2};
return b;
}

There are two kinds of array in Objective-C: standard C arrays and Cocoa NSArrays. C arrays hold primitive ints but are quite troublesome due to the limitations of C. NSArrays have to hold objects, but you can just wrap ints in NSNumbers and get the int value back out when you need it.
NSArray *array = [NSArray arrayWithObjects:[NSNumber numberWithInt:1], [NSNumber numberWithInt:500], [NSNumber numberWithInt:12000], nil];

Related

Custom setter in objective c

I'm trying to declare a custom getter of a NSDictionary but I can't get it to work.
So far I have the #property declared and the synthesize syntax.
#property (nonatomic, strong) NSDictionary *variableDictionary;
#synthesize variableDictionary = _variableDictionary;
I want to declare a setter for the dictionary that gives it some standard values.
-(void)setVariableDictionary:(NSDictionary *)variableDictionary {
NSNumber *x = [NSNumber numberWithDouble:20];
NSNumber *a = [NSNumber numberWithDouble:10];
NSNumber *b = [NSNumber numberWithDouble:5];
NSDictionary *_variableDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:a, #"a", b, #"b", x, #"x", nil];
}
When I use the above method I get a warning unused variable, and if I remove the underscore from the NSDictionary variable definition, I get an error saying 'redefinition of variable dictionary'.
I'm not sure of the correct way to do this.
_variableDictionary is already declared.
Replace
NSDictionary *_variableDictionary = [[NSDictionary alloc]
initWithObjectsAndKeys:a, #"a", b, #"b", x, #"x", nil];
with
_variableDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:a, #"a", b, #"b", x, #"x", nil];
In your custom setVarableDictionary: setter method, when you write:
NSDictionary *_variableDictionary = _variableDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:a, #"a", b, #"b", x, #"x", nil];
this declares and sets value for a new local variable within the scope of your function only. The warning message you get is because that variable is not used before it goes out of scope.
Instead of creating a local variable, you should just set the value of the ivar that underlies your property, like this:
_variableDictionary = [NSDictionary dictionaryWithObjectsAndKeys:a, #"a", b, #"b", x, #"x", nil];
First off, the setter implementation doesn't really make any sense considering it will never change the value (it's only function is to initialize). Nonetheless (assuming this would change), if you want to test the value in your setter, you could make it look something like this
-(void)setVariableDictionary:(NSDictionary *)variableDictionary {
NSNumber *x = [NSNumber numberWithDouble:20];
NSNumber *a = [NSNumber numberWithDouble:10];
NSNumber *b = [NSNumber numberWithDouble:5];
_variableDictionary = [[NSDictionary alloc] initWithObjectsAndKeys:a, #"a", b, #"b", x, #"x", nil];
NSLog(#"%#", _variableDictionary);
}
This will tell you whether or not the method is even being called. If it's not then you won't get the NSLog message.
This works on my end, if it's not on yours then there is something else going on.
If I understood your question. This might help
-(void)setVariableDictionary:(NSDictionary *)newVariableDictionary
{
if (variableDictionary != newVariableDictionary) {
variableDictionary = newVariableDictionary;
}
}
in your code.
-(void)setVariableDictionary:(NSDictionary *)variableDictionary {
its normal that it will give you an error when you redeclare your parameter. (NSDictionary *)variableDictionary
Try doing it this way, set your property as mentioned below:
#property (nonatomic, strong,setter = setTheVariableDictionary:) NSDictionary *variableDictionary;
Remove
-(void)setVariableDictionary:(NSDictionary *)variableDictionary
and write is as
-(void)setVariableDictionary:(NSDictionary *)thevariableDictionary
Hope this helps you.

Perform arithmetic on two NSArray's in component wise fashion?

I have two NSArray objects and I want to add the two arrays together in a component wise fashion such that the int in array1 at index i is added to the int in array 2 at index i with the result added to a new array. Is there a faster way to do this than with standard for for (int i=0; i<[array1 count]; i++) type methods? For example, can you use c arrays, fast enumeration, blocks? I am particularly interested because I would like to add x number of arrays containing large number of objects. My current code is as follows:
NSArray *array1 = [NSArray arrayWithObjects:
[NSNumber numberWithInt:1],
[NSNumber numberWithInt:2],
[NSNumber numberWithInt:3],
[NSNumber numberWithInt:4],
nil];
NSArray *array2 = [NSArray arrayWithObjects:
[NSNumber numberWithInt:10],
[NSNumber numberWithInt:20],
[NSNumber numberWithInt:30],
[NSNumber numberWithInt:40],
nil];
NSMutableArray *resultArray = [[NSMutableArray alloc] initWithCapacity:[array1 count]];
for (int i=0; i<[array1 count]; i++) {
int result = [[array1 objectAtIndex:i] intValue] + [[array2 objectAtIndex:i] intValue];
[resultArray addObject:[NSNumber numberWithInt:result]];
}
Thanks, I appreciate any comments.
Here an example of doing this with blocks and concurrent enumeration:
NSArray *array1 = [NSArray arrayWithObjects:
[NSNumber numberWithInt:1],
[NSNumber numberWithInt:2],
[NSNumber numberWithInt:3],
[NSNumber numberWithInt:4],
nil];
NSArray *array2 = [NSArray arrayWithObjects:
[NSNumber numberWithInt:10],
[NSNumber numberWithInt:20],
[NSNumber numberWithInt:30],
[NSNumber numberWithInt:40],
nil];
NSMutableArray *resultArray = [[NSMutableArray alloc] initWithCapacity:[array1 count]];
for (int i=0; i<[array1 count]; i++) {
[resultArray addObject:[NSNull null]];
}
dispatch_queue_t resultArrayQueue = dispatch_queue_create("com.yourcompany.appname.resultsArrayQueue", DISPATCH_QUEUE_SERIAL);
[array1 enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
int num1 = [(NSNumber *)obj intValue];
int num2 = [[array2 objectAtIndex:idx] intValue];
NSNumber *result = [NSNumber numberWithInt:(num1 + num2)];
dispatch_async(resultArrayQueue, ^{
[resultArray replaceObjectAtIndex:idx withObject:result];
});
}];
NSLog(#"Result array: %#", resultArray);
Whether it's faster or not would require profiling to determine. My hunch is that it's not much faster, and may even be slower because of the (relatively small, but still extant) overhead of GCD dispatches. However, for more complex computation than simple addition, this gives you an idea of how to use concurrent enumeration to easily do something with each element in an array in a multicore-aware way.
If you had x number of arrays in a top-level array (as described in your comment), you could replace the -enumerateObjectsWithOptions:usingBlock: call with something like this:
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(numberOfItemsInEachArray, globalQueue, ^(size_t idx) {
NSInteger sum = 0;
for (NSArray *array in parentArray) {
sum += [[array objectAtIndex:idx] integerValue];
}
NSNumber *result = [NSNumber numberWithInteger:sum];
dispatch_async(resultArrayQueue, ^{
[resultArray replaceObjectAtIndex:idx withObject:result];
});
});
dispatch_apply() is a Grand Central Dispatch function that simply runs a block of code a specified number of times. Since we're telling it to use a global concurrent queue that we got with dispatch_get_global_queue(), it can run different invocations of the block concurrently, providing a (possible) performance benefit on multicore machines. As with most programming problems, there are plenty of other ways to approach this problem. This is just one that came to mind for me.
You really can't get around having to go over both arrays at least once if you want to sum them up. However, you could look at the array as a matrix. In that context, there are some extremely fast matrix arithmetic algorithms or libraries for you to use.

iPhone: counting unique items in an array [duplicate]

I need to perform what I feel is a basic function but I can't find any documentation on how to do it. Please help!
I need to count how many times a certain object occurs in an array. See example:
array = NSArray arrayWithObjects:#"Apple", #"Banana", #"Cantaloupe", #"Apple", #"DragonFruit", #"Eggplant", #"Apple", #"Apple", #"Guava",nil]retain];
How can I iterate through the array and count the number of times it finds the string #"Apple"?
Any help is appreciated!
One more solution, using blocks (working example):
NSInteger occurrences = [[array indexesOfObjectsPassingTest:^(id obj, NSUInteger idx, BOOL *stop) {return [obj isEqual:#"Apple"];}] count];
NSLog(#"%d",occurrences);
As #bbum said, use an NSCounted set. There is an initializer thet will convert an array directly into a counted set:
NSArray *array = [[NSArray alloc] initWithObjects:#"A", #"B", #"X", #"B", #"C", #"D", #"B", #"E", #"M", #"X", nil];
NSCountedSet *countedSet = [[NSCountedSet alloc] initWithArray:array];
NSLog(#"%#", countedSet);
NSLog output:
(D [1], M [1], E [1], A [1], B [3], X [2], C [1])
Just access items:
count = [countedSet countForObject: anObj]; ...
A Simple and specific answer:
int occurrences = 0;
for(NSString *string in array){
occurrences += ([string isEqualToString:#"Apple"]?1:0); //certain object is #"Apple"
}
NSLog(#"number of occurences %d", occurrences);
PS: Martin Babacaev's answer is quite good too. Iteration is faster with blocks but in this specific case with so few elements I guess there is no apparent gain. I would use that though :)
Use an NSCountedSet; it'll be faster than a dictionary and is designed to solve exactly that problem.
NSCountedSet *cs = [NSCountedSet new];
for(id anObj in someArray)
[cs addObject: anObj];
// then, you can access counts like this:
.... count = [cs countForObject: anObj]; ...
[cs release];
Just came across this pretty old question. I'd recommend using a NSCountedSet:
NSCountedSet *countedSet = [[NSCountedSet alloc] initWithArray:array];
NSLog(#"Occurrences of Apple: %u", [countedSet countForObject:#"Apple"]);
I would encourage you to put them into a Dictionary (Objective C's version of a map). The key to the dictionary is the object and the value should be the count. It should be a MutableDictionary of course. If the item is not found, add it and set the count to 1.
- (int) numberOfOccurrencesForString:(NSString*)needle inArray:(NSArray*)haystack {
int count = 0;
for(NSString *str in haystack) {
if([str isEqualToString:needle]) {
count++;
}
}
return count;
}
I up-voted Rob's answer, but I wanted to add some code that I hope will be of some assistance.
NSArray *array = [[NSArray alloc] initWithObjects:#"A", #"B", #"B", #"B", #"C", #"D", #"E", #"M", #"X", #"X", nil];
NSMutableDictionary *dictionary = [[NSMutableDictionary alloc]init];
for(int i=0; i < [array count]; i++) {
NSString *s = [array objectAtIndex:i];
if (![dictionary objectForKey:s]) {
[dictionary setObject:[NSNumber numberWithInt:1] forKey:s];
} else {
[dictionary setObject:[NSNumber numberWithInt:[dictionary objectForKey:s] intValue]+1 forKey:s];
}
}
for(NSString *k in [dictionary keyEnumerator]) {
NSNumber *number = [dictionary objectForKey:k];
NSLog(#"Value of %#:%d", k, [number intValue]);
}
If the array is sorted as in the problem statement then you don't need to use a dictionary.
You can find the number of unique elements more efficiently by just doing 1 linear sweep and incrementing a counter when you see 2 consecutive elements being the same.
The dictionary solution is O(nlog(n)), while the linear solution is O(n).
Here's some pseudo-code for the linear solution:
array = A,B,B,B,B,C,C,D,E,M,X,X #original array
array = array + -1 # array with a dummy sentinel value to avoid testing corner cases.
# Start with the first element. You want to add some error checking here if array is empty.
last = array[0]
count = 1 # you have seen 1 element 'last' so far in the array.
for e in array[1..]: # go through all the elements starting from the 2nd one onwards
if e != last: # if you see a new element then reset the count
print "There are " + count + " " + last elements
count = 1 # unique element count
else:
count += 1
last = e
the complete code with reference to #bbum and #Zaph
NSArray *myArray = [[NSArray alloc] initWithObjects:#"A", #"B", #"X", #"B", #"C", #"D", #"B", #"E", #"M", #"X", nil];
NSCountedSet *countedSet = [[NSCountedSet alloc] initWithArray:myArray];
for (NSString *item in countedSet) {
int count = [countedSet countForObject: item];
NSLog(#"the String ' %# ' appears %d times in the array",item,count);
}
Thank you.
If you want it more generic, or you want to count equals/different objects in array, try this:
Sign "!" count DIFFERENT values. If you want SAME values, remove "!"
int count = 0;
NSString *wordToCheck = [NSString string];
for (NSString *str in myArray) {
if( ![str isEqualToString:wordToCheck] ) {
wordToCheck = str;
count++;
}
}
hope this helps the community!
I've used it to add correct number of sections in uitableview!
You can do this way,
NSArray *array = [[NSArray alloc] initWithObjects:#"A", #"B", #"X", #"B", #"C", #"D", #"B", #"E", #"M", #"X", nil];
NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:array];
NSArray *uniqueStates = [[orderedSet set] allObjects];
NSCountedSet *countedSet = [[NSCountedSet alloc] initWithArray:array];
for(int i=0;i<[uniqueStates count];i++){
NSLog(#"%# %d",[uniqueStates objectAtIndex:i], [countedSet countForObject: [uniqueStates objectAtIndex:i]]);
}
The result is like : A 1

Executing Blocks From NSArray?

I was just thinking, as you can treat Blocks like objects if I create two of them and then add them to an NSArray is there a way to execute them from the array?
int (^Block_001)(void) = ^{ return 101; };
int (^Block_002)(void) = ^{ return 202; };
NSArray *array = [NSArray arrayWithObjects:Block_001, Block_002, nil];
EDIT: Update for clarity Per #davedelong's excellent answer
int (^Block_001)(void) = [^{ return 101; } copy];
int (^Block_002)(void) = [^{ return 202; } copy];
NSArray *array = [NSArray arrayWithObjects:Block_001, Block_002, nil];
[Block_001 release];
[Block_002 release];
#KennyTM and #David are correct, but your code is potentially wrong. Here's why:
When creating an NSArray with objects, it will retain the objects put into it. In the case of blocks, it's using the Block_retain function. This means that the array has retained the blocks that you created, but that live on the stack (blocks are one of the very rare examples of Objective-C objects that can be created on the stack without delving into absurd tricks). That means that as soon as this method exits, your array now points to garbage, because the blocks it was pointing to no longer exist. To do this properly, you should do:
int (^Block_001)(void) = [^{ return 101; } copy];
int (^Block_002)(void) = [^{ return 202; } copy];
NSArray *array = [NSArray arrayWithObjects:Block_001, Block_002, nil];
[Block_001 release];
[Block_002 release];
By invoking copy on the block, you're explicitly moving the block off of the stack and onto the heap, where it can safely remain after the method/function exits. Then after you've added the blocks to the array, you have to balance your copy (because of the NARC rule) with a subsequent call to release. Make sense?
Sure, you just invoke it with () like any other block, but you need to typecast the value you retrieve from NSArray. Here's an example (with an added typedef, because otherwise my head hurts):
typedef int (^IntBlock)(void);
IntBlock Block_001 = ^{ return 101; };
IntBlock Block_002 = ^{ return 202; };
NSArray *array = [NSArray arrayWithObjects:Block_001, Block_002, nil];
int x = ((IntBlock)[array objectAtIndex:0]) (); // now x == 101
Of course you can.
int (^x)(void) = [array objectAtIndex:0];
printf("%d\n", x()); // prints 101.

Comparing Two Arrays

I have two NSArrays, what I'm looking to do is to compare two arrays which contain strings, find the similarities and create the first array again but so they have no similarities.
Just for an example something like.
Two Arrays:
NSArray *arrayOne = [NSArray arrayWithObjects:#"TD1", #"TD2", #"TD3", nil];
NSArray *arrayTwo = [NSArray arrayWithObjects:#"Blah", #"String", #"TD2", nil];
Outcome:
NSArray *arrayOne = [NSArray arrayWithObjects:#"TD1", #"TD2", #"TD3", nil];
NSArray *arrayOneCopy = [NSArray arrayWithObjects:#"TD1", #"TD3", nil];
NSArray *arrayTwo = [NSArray arrayWithObjects:#"Blah", #"String", #"TD2", nil];
NSMutableArray *arrayOneCopy = [NSMutableArray arrayWithArray:arrayOne];
[arrayOneCopy removeObjectsInArray:arrayTwo];
Use NSMutableSet:
NSMutableSet *setOne = [NSMutableSet setWithArray: arrayOne];
NSMutableSet *setTwo = [NSMutableSet setWithArray: arrayTwo];
[setOne minusSet: setTwo];
NSArray *arrayOneResult = [setOne allObjects];
(strictly speaking, setTwo doesn't have to be mutable, can also be an NSSet (which performs better))
Or use NSArray as the other person answered -- that works, too.
Which one works depends entirely on your data set size. For small sets of data, the array solution works fine. For larger sets, NSSet will be much more efficient in that membership tests are a hash check and not a linear search.
Measure and use the one that works best.
- (NSInteger)countOfDifferentObjects:(NSArray *)anotherArray {
NSSet * s = [NSSet setWithArray:self];
NSMutableSet * s1 = [NSMutableSet setWithSet:s];
NSSet * s2 = [NSSet setWithArray:anotherArray];
[s1 unionSet:s2];
[s1 minusSet:s];
return [s1 count];
}
This returns the number of different objects between two arrays (comparison is with isEqual)
array1 = #"A", #"B", #"C"
array2 = #"B", #"D", #"Z"
returns 2 (D and Z are different)