Objective C NSMutableArray work with nil - objective-c

I want to create a NSMutableArray to represent a game board that holds grid element (assume I have a chess class). In this case, I already know the size of the board so I want to create an array by initWithCapacity:[size] and then initialize them as nil. During the game, I may insert or remove chess object into/from this array based on game. I need to check if some cell is nil sometimes.
Clearly initWithCapacity only allocate memory, but gives an empty array whose element is not assessable. I think insert [NSNull null] one by one is inefficient (I can turn to use 0 to represent nil but still not what I want).
Is there any type/structure in Objective C like a C/C++ array for my purpose? Or is it wise to use C/C++ array here? (e.g. Chess myArray[size])

It is by design that NSMutableArrays and other collections do not permit nil and [NSNull null] is used as a placeholder for the concept of "nothing" instead.
I think insert [NSNull null] one by one is inefficient
[NSNull null] is a singleton, so won't allocate lots of memory unnecessarily and is not inefficient.
This answer has more information.
Anther efficiency I'm concerning about [NSNull null] is when I first create the array, if this array is kind of large (say 100 entries)
100 elements isn't a problem. Your device will be able to iterate 100 elements very quickly. Time it if you like.
is enumeration the only way I can assign a nil to each of these 100 entries? (e.g. for (i=0;i<size;i++) {[myArray addObject:[NSNull null]];}
It's the first way I would think of doing it.
"Premature optimisation is the root of all evil"
Donald Knuth
You seem to be concentrating on optimisation too early. You should favour readability over efficiency at this point.
When your app seems to slow down, or near the end of a release, profile the application and find out what, if any problems exist. Otherwise you may find yourself spending a day "optimising" a for loop to find that you've saved 0.000001s per update.
Moreover, readable code is easier to:
debug
update
maintain
share
Micro-optimised code takes longer to produce, is prone to bugs, difficult to debug and maintain and often impossible to share as another developer may not know how to interpret your optimisations.
That's not to say "don't optimise", rather concentrate on optimising the biggest problems.

You can use something like this:
NSMutableArray *array = [NSMutableArray arrayWithArray:#[#"First", #"Second", #"Third"]];
[array addObject:[NSNull null]];
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if (![obj isKindOfClass:[NSNull class]]) {
// Do something
}
}];

Related

performance for reads of nsdictionary vs nsarray

Continuing off this post: Performance hit incurred using NSMutableDictionary vs. NSMutableArray>
I am trying to run a little test to see if the performance gap is that great for read and writes between NSArray & NSDictionary as well as their mutable coutnerparts...
However, I am having difficulties finding a "balanced" test... because the dictionary has 2 (or 3 depending on how you see this) objects to loop through to get the value (not the key) seeked, while the array has only one...
Any suggestions?
--If you want more details:
What I mean is easier to explain through examples;
For the array:
(for NSString *str in array) { do smth with the string }
For the dictionary
(for NSString *str in [dictionary allValues]) { string }
OR
(for NSString *str in [dictionary allKeys]) { [dictionary valueForKey:key] }
OR
(for NSString *str in [dictionary allKeys]) { string }
OR EVEN
NSArray *valuesOrKeys = [dictionary allKeys/allValues];
(for NSString *str in valuesOrKeys) {string }
What is the "fairest" test to do for the dictionary?
--EDIT (comment)
As you all pointed (and asked why I would want that) that when a dictionary is used, it's because it fits the model better than an array...
well the reason for my asking is that an app I'm building is painfully slow and so I'm trying to figure out if the use of a different datatype would change any of that, and I am considering using basic c arrays... I have the choice at this point so I am able to change the inner workings to fit whatever type I want...
I'd like to point you at the following article: "Array", by ridiculous_fish, an engineer at Apple. Cocoa arrays are not necessarily well-implemented naïve arrays as you might expect, nor are dictionaries simple hash tables. Their performance is very circumstantial, and depends on the number of objects they hold (as well as their values, etc.). This might not directly affect the answer, but it's something to consider (NSDictionary performance will, of course, vary with the speed and reliability of your hashing function, and so on).
Additionally, if you're looking for a 'balanced' test, you'd have to look for a way for both classes to behave as close to each other as possible. You want to rule out accessing values via keys in the dictionary, because that — regardless of how fast seek times are for the underlying data structures maintained by NSDictionary — is slower than simply pulling objects from an array because you're performing more operations to do it. Access from an array is O(1), for a hash table, O(1) at best and O(n) at worst (depending on the implementation, somewhere in the middle).
There are several ways to enumerate both dictionaries and arrays, as you mentioned above. You're going to want to use the methods that are closest to each other in terms of implementation, those being either block-based enumeration (enumerateObjectsUsingBlock: for NSArray and enumerateKeysAndObjects: for NSDictionary), or fast enumeration (using either allKeys or allValues for the NSDictionary). Because the performance of these algorithms is mainly empirical, I performed several tests to note access times (each with 10000 NSNumber objects):
NSArray, Block Enumeration:
1. 10.5s
2. 9.1s
3. 10.0s
4. 9.8s
5. 9.9s
-----
9.9s Avg
NSArray, Fast Enumeration:
1. 9.7s
2. 9.5s
3. 9.3s
4. 9.1s
5. 10.5s
-----
9.6s Avg
NSDictionary, Block Enumeration
1. 10.5s
2. 10.6s
3. 9.9s
4. 11.1s
5. 11.0s
-----
10.6s Avg
NSDictionary, allKeys -> Fast Enumeration
1. 10.0s
2. 11.2s
3. 10.2s
4. 10.8s
5. 10.8s
-----
10.6s Avg
NSDictionary, allValues -> Fast Enumeration
1. 10.7s
2. 10.3s
3. 10.5s
4. 10.5s
5. 9.7s
-----
10.3s Avg
As you can see from the results of this contrived test, NSDictionary is clearly slower than NSArray (around 7% slower using block enumeration, and 7–10% slower with fast enumeration). However, this comparison is rather pointless, seeing as using the fastest enumeration for NSDictionary simply devolves it into an array anyway.
So the big question is, why would you consider using a dictionary? Arrays and hash tables aren't exactly interchangeable; what kind of model do you have that allows drop-in replacement of NSArray with NSDictionary? Regardless of the times given by contrived examples to prove performance benefits one way or another, you should always implement your models in a way that makes sense — you can optimize later for performance if you have to. I don't see how you would uses these data structures interchangeably, but anyway, NSArray is the winner here, especially considering the sequential order in which you're attempting to access values.
Here's your "balanced" test using fast enumeration:
[arr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
// do something with objects
}];
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
// do something with objects
}];
I am trying to run a little test to see if the performance gap is that
great for read and writes between NSArray & NSDictionary as well as
their mutable coutnerparts...
Why? If it's just to satisfy your curiosity, that's one thing. But usually if you need a dictionary, an array really won't do, and vice versa. So it doesn't matter which one is faster at a given operation -- it's not like one is good alternative for the other.
However, I am having difficulties finding a "balanced" test... because
the dictionary has 2 (or 3 depending on how you see this) objects to
loop through to get the value (not the key) seeked, while the array
has only one...
You're making some assumptions here that aren't likely to be valid. There's probably not a lot of looping involved to access elements of either kind of container.

In Objective-C, if addObjectAtIndex is called to built the array, then will initWithCapacity need to be called?

In a book, I see the code:
words = [[NSMutableArray alloc] initWithCapacity:[masterWordList count]];
and let's say [masterWordList count] is 15. And then the code built the array up by using a loop for 10 times:
[words addObject:[masterWordList objectAtIndex:randomNum]];
I wonder why words has to be initWithCapacity... and to 15 slots? Can't it be 10 or 11 (if a nil is needed at the end... and also, won't addObject automatically grow the array size? I tried using init instead of initWithCapacity and the code worked too. So can the code in the book be simplified to just init?
initWithCapacity: simply gives the class initializer a "hint" as to the eventual size of the array. That way, it can allocate enough space in advance if you know you're going to need it. Using initWithCapacity: can theoretically provide for better performance because it may mean that the array doesn't have to reallocate memory (internally) as you add objects to it (I don't know if it actually does this in the current implementation, but it's possible). As you've guessed, it's only a hint and using initWithCapacity: is entirely optional. Just because you've given initWithCapacity: a certain size doesn't mean your array can't grow to hold more elements than that. Also, calling init instead will work just fine.
I wonder why words has to be initWithCapacity... and to 15 slots?
In fact, initWithCapacity: is generally not necessary at all. It may or may not reserve space in a useful way. My understanding is that it's something of a historic appendage.
Can't it be 10 or 11 (if a nil is needed at the end...)
It could be 10. As was mentioned on your other question, nil isn't part of the array. It's just a sentinel value for the creating method call itself -- it's not an object and doesn't become a member of the collection.
also, won't addObject: automatically grow the array size?
Yes it will; you can create a mutable array without specifying any starting size and it will grow as needed.
So can the code in the book be simplified just to init?
Yes.

NSMutableArray vs NSArray which is better

This is a bit of a silly question, but if I want to add an object to an array I can do it with both NSMutableArray and NSArray, which should I use?
NSMutableArray * array1;
[array1 addObject:obj];
NSArray * array2;
array2 = [array2 arrayByAddingObject:obj];
Use NSMutableArray, that is what it is there for. If I was looking at code and I saw NSArray I would expect it's collection to stay constant forever, whereas if I see NSMuteableArray I know that the collection is destined to change.
It might not sound like much right now, but as your project grows and as you spend more time on it you will see the value of this eventually.
NSMutableArray is not threadsafe, while NSArray is. This could be a huge problem if you're multithreading.
NSMutableArray and NSArray both are build on CFArray, performance/complexity should be same. The access time for a value in the array is guaranteed to be at
worst O(lg N) for any implementation, current and future, but will
often be O(1) (constant time). Linear search operations similarly
have a worst case complexity of O(N*lg N), though typically the
bounds will be tighter, and so on. Insertion or deletion operations
will typically be linear in the number of values in the array, but
may be O(N*lg N) clearly in the worst case in some implementations.
When deciding which is best to use:
NSMutableArray is primarily used for when you are building collections and you want to modify them. Think of it as dynamic.
NSArray is used for read only inform and either:
used to populate an NSMutableArray, to perform modifications
used to temporarily store data that is not meant to be edited
What you are actually doing here:
NSArray * array2;
array2 = [array2 arrayByAddingObject:obj];
is you are creating a new NSArray and changing the pointer to the location of the new array you created.
You are leaking memory this way, because it is not cleaning up the old Array before you add a new object.
if you still want to do this you will need to clean up like the following:
NSArray *oldArray;
NSArray *newArray;
newArray = [oldArray arrayByAddingObject:obj];
[oldArray release];
But the best practice is to do the following:
NSMutableArray *mutableArray;
// Initialisation etc
[mutableArray addObject:obj];
An NSArray object manages an immutable array—that is, after you have created the array, you cannot add, remove, or replace objects. You can, however, modify individual elements themselves (if they support modification). The mutability of the collection does not affect the mutability of the objects inside the collection. You should use an immutable array if the array rarely changes, or changes wholesale.
An NSMutableArray object manages a mutable array, which allows the addition and deletion of entries, allocating memory as needed. For example, given an NSMutableArray object that contains just a single dog object, you can add another dog, or a cat, or any other object. You can also, as with an NSArray object, change the dog’s name—and in general, anything that you can do with an NSArray object you can do with an NSMutableArray object. You should use a mutable array if the array changes incrementally or is very large—as large collections take more time to initialize.
Even the Q and the answer are very old, someone has to correct it.
What does "better" mean? Better what? Your Q leaks of information what the problem is and it is highly opinion-based. However, it is not closed.
If you are talking about performance, you can measure it yourself. But remember Donald Knuth: "Premature optimization is the root of all evil".
If I take your Q seriously, "better" can mean runtime performance, memory footprint, or architecture. For the first two topics it is easy to check yourself. So no answer is needed.
On an architectural point of view, things become more complicated.
First of all I have to mention, that having an instance of NSArray does not mean, that it is immutable. This is, because in Cocoa the mutable variants of collections are subclasses of the immutable variants. Therefore an instance of NSMutableArray is an instance of NSArray, but obviously mutable.
One can say that this was no good idea, especially when thinking about Barbara and Jeanette and there is a relation to the circle-ellipse problem, which is not easy to solve. However, it is as it is.
So only the docs can give you the information, whether a returned instance is immutable or not. Or you do a runtime check. For this reason, some people always do a -copy on every mutable collection.
However, mutability is another root of all evil. Therefore: If it is possible, always create an instance of NSArray as final result. Write that in your docs, if you return that instance from a method (esp. getter) or not, so everyone can rely on immutability or not. This prevents unexpected changes "behind the scene". This is important, not 0.000000000003 sec runtime or 130 bytes of memory.
This test gives the best answer:
Method 1:
NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate];
NSMutableArray *mutableItems = [[NSMutableArray alloc] initWithCapacity:1000];
for (int i = 0; i < 10000; i++) {
[mutableItems addObject:[NSDate date]];
}
NSTimeInterval end = [NSDate timeIntervalSinceReferenceDate];
NSLog(#"elapsed time = %g", (end - start) * 1000.0);
Method 2:
...
NSArray *items = [[[NSArray alloc] init] autorelease];
or (int i = 0; i < 10000; i++) {
items = [items arrayByAddingObject:[NSDate date]];
}
...
Output:
Method 1: elapsed time = 0.011135 seconds.
Method 2: elapsed time = 9.712520 seconds.

NSSet -member to check equality of NSValue

I have a NSSet containing many thousands of NSValue objects (wrapping CGPoints). I would like to very quickly find if a given CGPoint value exists in the NSSet. It seems to me that the member: method of an NSSet might do the job here, except that it checks for equality using isEqual:. NSValue objects use isEqualToValue:, and so when I execute the code:
[mySet member:valueToCheck];
it actually causes Xcode to crash.
1) Is there some way to use a custom equality check to make this work for NSValue objects?
2) Is this even the best approach (i.e. is member: quick enough in the first place)? The scenario is that I have a NSSet containing a large number of points representing pixels on the screen (iPad). Later on I need to bombard that set with many thousands of points per second to see if they exist in the set. My approach seems crude for achieving this. I thought about creating something like a huge 2-dimensional bit array, with each index representing a pixel on screen. Once I know the point I'm testing for, I can just jump straight to that point in the array and check for a 1 or 0... does this sound better or worse?
Thanks
Can you get this to a simple reproducible case? For example, I just tried:
NSValue *v = [NSValue valueWithCGPoint:CGPointMake(1, 1)];
NSSet *s = [NSSet setWithObject:v];
NSLog(#"%#", [s member:[NSValue valueWithCGPoint:CGPointMake(1, 1)]]);
But it works just fine.
edit
-isEqual: is not the problem:
NSValue *v1 = [NSValue valueWithPoint:NSMakePoint(1, 1)];
NSValue *v2 = [NSValue valueWithPoint:NSMakePoint(1, 1)];
NSLog(#"%d", [v1 isEqual:v2]); //logs "1"
-hash is not the problem:
NSLog(#"%d", ([v1 hash] == [v2 hash])); //logs "1"
They are different objects:
NSLog(#"%d", (v1 != v2)); //logs "1"
The problem is in your code. Try cleaning and rebuilding.
To answer no. 2:
I don't know how NSSet is implemented internally, but considering that you know you are storing points (with X and Y), I think you would be better by implementing your own partitioning algorithm. Personally I would choose my own implementation over NSSet if you say you have thousands of points.
Storing huge 2-dimensional arrays for each pixel, would probably be the fastest way, but it will kill you in terms of memory consumption. You need something fast, but also lightweight.
There are a lot of algorithms out there and you can find them by searching "spatial partitioning algorithms" on wikipedia or google. It also depends on your programming skills, and how much time you are willing to invest in this.
For example, a pretty simple one would be to implement a quad-tree, where you start by diving your screen(or area) in 4 equal parts. Then if and where is needed, you divide that specific cell also in 4 parts. And you do this until each cell contains a small enough number of points so that you can brute-force test all of them.
You can find a very good description on wiki: http://en.wikipedia.org/wiki/Quadtree
Hope this helps,
[mySet member:valueToCheck] should not be crashing. NSValue's isEqual: works fine when I try it here, and in fact probably calls isEqualToValue: when given another NSValue to compare to. Is valueToCheck really an NSValue, or is it a CGPoint?
There is no way to override the default hash and comparison methods for NSSet. But NSSet is toll-free bridged with CFSetRef, and you can easily specify custom hashing and comparison methods there:
CFSetCallBacks callbacks = kCFTypeSetCallBacks;
callbacks.equal = customEqualFunction;
callbacks.hash = customHashFunction;
NSMutableSet *set = (NSMutableSet *)CFSetCreateMutable(NULL, 0, &callbacks);
The constraints on these functions are presumably the same as on NSObject's hash and isEqual: methods, anything that is equal must have the same hash. The C-style prototypes for customEqualFunction and customHashFunction are described here and here.
One solution would be to subclass NSSet and override member: to do your own comparison. Your own comparison could then simple call isEqualToValue:. Have a look at the subclassing notes in the NSSet documentation.
Another approach would be to add a category to NSValue that implements isEqual:. In this case I'd prefer subclassing because it's a more constrained solution.
It's not just a problem with -isEqual:, you may also have an issue with the -hash method. If you want to use an NSSet, you should probably create a custom class that wraps the CGPoint. -isEqual: is then trivial and -hash could be implemented by some method of combining the bits of both coordinates and then treating them as a NSUInteger.
You'll also want to implement the NSCopying protocol which is also trivial if your points are immutable (just retain and return self in -copyWithZone:).

How can I remove the first element of an array in Objective C?

In Objective C, is there a one-liner or something small to remove (shorten by one) and return the first element of an array, regardless of its index?
I don't know of a method that returns the item removed, but you can do this using a combination of NSArray#objectAtIndex:0 and NSMutableArray#removeObjectAtIndex:0. I suppose you could introduce a new method category on NSMutableArray that implements a shift method.
That would be a poor thing to do.
Objective-C on the iPhone can actually use most of the performance perks of C.
If you look at some of my other posts, you'll see I'm ADAMANTLY against premature optimization, but when you are coding at the C level, there are just some things you don't do unnecessarilly.
Move memory
Duplicate structures
Allocate sparsely populated memory blocks
Inner loops
... (There are lots more, but my C-life is rusty and, as I said, I'm anti-optimization)
What you probably want is a well-implemented queue. Something that pre-allocates a large enough circular memory structure and then has two pointers that track the first and last bytes.
I'd be pretty surprised to hear that Objective-C didn't have a queue data structure.
Also, don't strive for the one-liners. All the stuff about terse code is overrated. If it makes more sense to call a method, so be it.
It's certainly too late to assist the original poster, but if you have a plain NSArray and not an NSMutableArray, this works well:
id myData = myArray.firstObject;
myArray = [myArray subarrayWithRange:NSMakeRange(1, myArray.count - 1)];
Cocoa array objects (NSArray/NSMutableArray) do not provide a one-line equivalent — you would have to read the object first, then remove it. The fact that these classes provide the methods -lastObject and -removeLastObject but not -firstObject and -removeFirstObject should be a reminder that removing from the front of an array is usually an inefficient operation, since the contents must be shifted (copied) one position forward. This is particular true for arrays in C, which are intrinsically tied with pointers.
If you're working with anything but primitive data types and/or very small arrays, you might want to consider that the behavior of "shifting off" the first element is indicative of a queue data structure. For details on how you might create a queue for objects, see this SO question. Personally, my opinion for that question is that a real queue class provides the cleanest programming idiom. You can even define your own method (perhaps as a category on NSMutableArray or another class) that does provide a one-liner to do what you want:
#interface NSMutableArray (QueueOneLiner)
- (id) removeAndReturnFirstObject; // Verbose, but clearer than "shift"
#end
#implementation NSMutableArray (QueueOneLiner)
- (id) removeAndReturnFirstObject {
id object = [[self objectAtIndex:0] retain];
[self removeObjectAtIndex:0];
return [object autorelease];
}
#end
However, by that point the solution will likely cause more overhead than it's worth, depending on the importance you place on simplicity versus performance of the code that uses it.
If you have an array obj *arr where obj is a class/typename and arr is the array, you can just say arr+1 to get the array without the first element.
Use this code,
[arrayName removeObjectAtIndex:0];
this may help you