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

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.

Related

NSDictionary creation inside loop with ARC

I'm having a big trouble while creating NSDictionaries inside a for-loop while using ARC. The point is that after the first "dict" creation, the app crashes giving an EXC_BAD_ACCESS so I presume it's something related to the release of the object, but can't figure out what! I tried using an autoreleasepool but the result was the same
for (int i = 0; i < [arr1 count]; i++) {
__strong NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[arr1 objectAtIndex:i], #"name", [arr4 objectAtIndex:i], #"position", [arr2 objectAtIndex:i], #"number", [arr5 objectAtIndex:i], #"status", [[arr6 objectAtIndex:i] intValue], #"order", nil];
[pl_stuff addObject:dict];
}
thanks for your replies
[[arr6 objectAtIndex:i] intValue]
You're trying to add plain integer value to your array, but array accept only objective-c objects. You should probably just leave that as:
[arr6 objectAtIndex:i]

how to create an array of string or float in Objective-C

i need some help here, i need to know how to create an array of string retrieved from an array. i'm using powerplot for graph and it only accept float or string array.
i need to create something something like this dynamically.
NSString * sourceData[7] = {#"2", #"1", #"4", #"8", #"14", #"15", #"10"};
Below are my code to find out the numbers in strings.
NSInteger drunked = [appDelegate.drinksOnDayArray count];
NSMutableArray * dayArray = [[NSMutableArray alloc] init];
NSMutableArray * sdArray = [[NSMutableArray alloc] init];
//float *sdArray[7];
for (int i=0; i<drunked; i++) {
DayOfDrinks *drinksOnDay = [appDelegate.drinksOnDayArray objectAtIndex:i];
NSString * dayString= [NSDate stringForDisplayFromDateForChart:drinksOnDay.dateConsumed];
[dayArray addObject:dayString];
NSLog(#"%#",[dayArray objectAtIndex:i]);
drinksOnDay.isDetailViewHydrated = NO;
[drinksOnDay hydrateDetailViewData];
NSString * sdString= [NSString stringWithFormat:#"%#", drinksOnDay.standardDrinks];
[sdArray addObject:sdString];
NSString *tempstring;
NSLog(#"%#",[sdArray objectAtIndex:i]);
}
thanks for the help :)
Array's in Objectice-C aren't that hard to work with:
NSMutableArray *myArray = [NSMutableArray array];
[myArray addObject:#"first string"]; // same with float values
[myArray addObject:#"second string"];
[myArray addObject:#"third string"];
int i;
int count;
for (i = 0, count = [myArray count]; i < count; i = i + 1)
{
NSString *element = [myArray objectAtIndex:i];
NSLog(#"The element at index %d in the array is: %#", i, element); // just replace the %# by %d
}
You can either use NSArray or NSMutableArray - depending on your needs, they offer different functionality.
Following tutorial covers exactly what you are looking after:
http://www.cocoalab.com/?q=node/19
You can also add the elements to the array when you init (and optionally add them later only if you are using the Mutable version of a collection class:
NSMutableArray *myArray = [[NSMutableArray alloc] initWithObjects:#"2", #"1", #"4", #"8", #"14", #"15", #"10", nil];
[myArray addObject:#"22"];
[myArray addObject:#"50"];
//do something
[myArray release];
You can use malloc to create a C-style array. something like this should work:
NSString **array = malloc(numElements * sizeof(NSString *))
some code here
free(array)
Be aware that unlike NSMutable array, c arrays won't do a retain, so you have to manage it if needed. And don't forget the free

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

Ask about int array in Objective-C

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];

Algorithm: Keeping count of key/value pair in NSDictionary

Being new to Cocoa, and probably not knowing all of the potential classes available that already have this functionality neatly wrapped in an OO class, here's an algorithm inquiry. What's the best bet to count how many times a particular key occurs in an array of multiple NSDictionary instances?
Essentially my data structure (in this case an NSArray) might contain several NSDictionary instances at any given time, each one having the same keys, potentially different values. Some values repeat. I'd like to be able to know how many times a particular key/value appears. Example:
{
foo => 1,
bar => 2
}
{
foo => 1,
bar => 3
}
{
foo => 2,
bar => 1
}
In this case I'm interested that foo=>1 occured 2 times and foo=>2 occured 1 time. Is building an instance of NSCountedSet the best way to go about this? Perhaps a C linked-list?
You may want to rethink how you are structuring your data. I'd track something like this while adding to the NSArray instead of trying to discover it at a later time. You might create a new class to handle adding and removing the data so that you can keep your own counts of the data.
NSDictionary * dict1 = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithInt:1], #"foo",
[NSNumber numberWithInt:2], #"bar", nil];
NSDictionary * dict2 = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithInt:1], #"foo",
[NSNumber numberWithInt:3], #"bar", nil];
NSDictionary * dict3 = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithInt:2], #"foo",
[NSNumber numberWithInt:1], #"bar", nil];
NSArray * arrayOfDictionaries = [[NSArray alloc] initWithObjects:
dict1, dict2, dict3, nil];
// count all keys in an array of dictionaries (arrayOfDictionaries):
NSMutableDictionary * countKeys = [[NSMutableDictionary alloc] initWithCapacity:0];
NSCountedSet * counts = [[NSCountedSet alloc] initWithCapacity:0];
NSArray * keys;
NSString * pairString;
NSString * countKey;
for (NSDictionary * dictionary in arrayOfDictionaries)
{
keys = [dictionary allKeys];
for (NSString * key in keys)
{
pairString = [NSString stringWithFormat:#"%#->%#", key, [dictionary valueForKey:key]];
if ([countKeys valueForKey:pairString] == nil)
{
[countKeys setValue:[NSString stringWithString:pairString] forKey:pairString];
}
countKey = [countKeys valueForKey:pairString];
{ [counts addObject:countKey]; }
}
}
NSLog(#"%#", counts);
[counts release];
[countKeys release];
[arrayOfDictionaries release];
[dict1 release];
[dict2 release];
[dict3 release];
NSCountedSet *keyCounts = [NSCountedSet set];
for (NSDictionary *dict in myDictionaries)
[keyCounts unionSet:[NSSet setWithArray:[dict allKeys]]];