It's just a matrix, damn it!
August 10, 2006 10:00 PM   Subscribe

How should I go about implementing a (potentially sparse) mutable 2d array of NSObjects in Objective-C, using any frameworks that are part of the OSX Tiger world?

There are three requirements: One, I must be able to set values at a given row and column to nil (or clear them), two: Assuming a matrix with n rows and m columns, I should be able to insert a new value at index (n+a, m+b) where a and b are any non-negative integers (automatically expanding to fit). Third, and last, is that if a value has never been set, but is within the bounds of the largest values that have been set, it should return nil, otherwise it should error.

The third requirement isn't strictly necessary, as that sort of bounds checking is something I can add on to it.

The reason this isn't easy for me, if anyone cares, is that I'm brand-spanking-new to Objective-C, Macs, and Cocoa, so this is all a bit weird -- especially the way that collections (to use the Java terminology) work.
posted by ChrisR to Computers & Internet (4 answers total)
 
Hmmm... this is a bit out of my league. If it's really, truly sparse you might want to experiment with an NSMutableDictionary of NSMutableDictionary's. Your keys in this case would be NSNumber's. To answer your points:

1) You can't directly store "nil" in a collection. That is, don't call [aDict setObject:nil forKey:[NSNumber numberWithInt:i]]. Instead, use either removeObjectForKey: or setObject:forKey: with NSNull (but you'll have to check each return value to see if it's NSNull).

2) You're not going to like this, but...
NSMutableDictionary *inner = [outter objectForKey:[NSNumber numberWithInt:(n+a)]];if (inner == nil){    inner = [NSMutableDictionary dictionary];    [outter setObject:inner forKey:[NSNumber numberWithInt:(n+a)]];}if (anObject == nil)    [inner removeObjectForKey:[NSNumber numberWithInt:(m+b)]];else    [inner setObject:anObject forKey:[NSNumber numberWithInt:(m+b)];
3) Not a problem if you use removeObjectForKey: everywhere. Otherwise, remember to check for NSNull.
posted by sbutler at 11:05 PM on August 10, 2006


The reason this isn't easy for me, if anyone cares, is that I'm brand-spanking-new to Objective-C, Macs, and Cocoa, so this is all a bit weird -- especially the way that collections (to use the Java terminology) work.

I find Apple's Cocoa-dev mailing list is usually an excellent resource for Objective C and Cocoa framework questions. It is moderated well, albeit with a heavy, rude hand towards those new to the language and API, so frame your questions well.

I also find the list archive, maintained in searchable format at Cocoabuilder, is a good secondary resource.

Also check out Cocoadevcentral for other useful code samples and tips.
posted by Blazecock Pileon at 6:51 AM on August 11, 2006


Response by poster: Hm. Looking at what you have, I just realized that I can achieve what I want using just a single dictionary, with a point-type object for a key. That's nicer than the NSMutableArray of NSMutableArrays that I had initially considered, and guaranteed to be infinitely expandable.

It'll require a bit of bookkeeping, in order to have size calculations, but getting/setting is easy, and I can even iterate reasonably well.

I know this is slightly off-topic to the question, but do you happen to have any insight on why the decision was made to prevent sparse collections by throwing exceptions on the insertion of nil?
posted by ChrisR at 6:51 AM on August 11, 2006


My hunch is that it has to do with the toll-free bridge with CFMutableDictionary and that you can't call CFRetain/CFRelease on NULL references.
posted by sbutler at 7:14 AM on August 11, 2006


« Older Examples of calculus trivia?   |   ADD + Alcohol = ? Newer »
This thread is closed to new comments.