Tony Hematite
Tony Hematite

Reputation: 149

Find the average of an NSMutableArray with valueForKeyPath

Currently I'm trying to find a compact way to average a matrix. The obvious solution is to sum the matrix, then divide by the number of elements. I have, however, come across a method on the apple developer website that claims this can be done in a simpler way using valueForKeyPath. This is linked here:

http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/KeyValueCoding/Articles/CollectionOperators.html

Here is the example I'm currently working on to try and get it to work:

-(void)arrayAverager
{
   NSMutableArray *myArray = [NSMutableArray arrayWithCapacity:25];
   [myArray addObject:[NSNumber numberWithInteger:myValue]];
   NSNumber *averageValue = [myArray valueForKeyPath:@"@avg.self"];
   NSLog(@"avg  = %@", averageValue);

} 

The problem is: instead of averaging the array it merely prints out the elements in the array 1 by 1.

UPDATE

-(void) pixelAverager

{
    //Put x-coordinate value of all wanted pixels into an array
    NSMutableArray *xCoordinateArray = [NSMutableArray arrayWithCapacity:25];
    [xCoordinateArray addObject:[NSNumber numberWithInteger:xCoordinate]];
    NSLog(@"avg = %@", [xCoordinateArray valueForKeyPath:@"@avg.intValue"]);
 }

Upvotes: 5

Views: 7717

Answers (2)

freespace
freespace

Reputation: 16701

You need to use @avg.floatValue (or @avg.doubleValue, or what have you). The @avg operator will average the property of the objects in the array specified by the name after the dot. The documentation is confusing on this point, but that is what:

to get the values specified by the property specified by the key path to the right of the operator

Is saying. Since you have a collection of NSNumber objects, you use one of the *value accessors, e.g. floatValue to get the value of each object. As an example:

#include <Foundation/Foundation.h>

int main(void) {
  NSMutableArray *ma = [NSMutableArray array];
  [ma addObject:[NSNumber numberWithFloat:1.0]];
  [ma addObject:[NSNumber numberWithFloat:2.0]];
  [ma addObject:[NSNumber numberWithFloat:3.0]];

  NSLog(@"avg = %@", [ma valueForKeyPath:@"@avg.floatValue"]);

  return 0;
}

Compiling and running this code returns:

$ clang avg.m -framework Foundation -o avg
steve:~/code/tmp
$ ./avg 
2013-01-18 12:33:15.500 avg[32190:707] avg = 2
steve:~/code/tmp

The nice thing about this approach is that this work for any collection, homogenous or otherwise, as long as all objects respond to the specified method, @avg will work.

EDIT

As pointed in the comments, the OP's problem is that he is averaging a collection with one element, and thus it appears to simply print the contents of the collection. For a collection of NSNumber objects, @avg.self works just fine.

Upvotes: 18

arthankamal
arthankamal

Reputation: 6413

No, you can't do like this. The object Transaction is a Modal Class. This class is having three properties, namely

  • payee
  • amount
  • date

Each row in this image represents one Transaction modal object.

enter image description here

transactions is an array which is holding all these rows (Transaction Modal Objects).

In these transactions array, they are trying to calculate the Transaction Modal amount field average using the operator @avg. So, its like

NSNumber *transactionAverage = [transactions valueForKeyPath:@"@avg.amount"];

your array doesn't have the key self. So that's the problem

Upvotes: -1

Related Questions