How can i make NSMutableArray only accept unique values? - objective-c

NSMutableArray *sectionTitles;
[sectionTitles addObject:due];
How do I just add unique values to an array?

See Rudolph's Answer
My old answer below is now outdated and has been for awhile. Rudoph's reference to NSOrderedSet / NSMutableOrderedSet is the correct one since these classes were added after this Q and my A.
Old Answer
As Richard said, NSMutableSet works well but only if you don't need to maintain an ordered collection. If you do need an ordered collection a simple content check is the best you can do:
if (![myMutableArray containsObject:newObject])
[myMutableArray addObject:newObject];
Update based on comment
You can wrap this in a method like -addUniqueObject: and put it in an NSMutableArray category.

More 2012-ish answer (in case someone stumbled upon this in the future):
Use NSOrderedSet and NSMutableOrderedSet.
A note about performance right from NSOrderedSet docs:
You can use ordered sets as an alternative to arrays when the order of elements is important and performance in testing whether an object is contained in the set is a consideration— testing for membership of an array is slower than testing for membership of a set.

Use NSMutableSet, it is best for these situations
iOS Reference
Mac OSX Reference

Related

Array from set: why does NSSet use allObjects, while NSOrderedSet uses array?

In Foundation, if I want to convert a set to an NSArray, I can use:
-[NSSet allObjects]
-[NSOrderedSet array]
Why are these different?
Speculation, but:
Because when NSSet was created the only other major collection type was NSArray, which was (and still is, largely) the most common collection type. So a method called "allObjects" would obviously return an NSArray.
When NSOrderedSet was added much more recently, it had to deal with the existence of prior collections - primarily, NSArray and NSSet. So an "allObjects" method would be ambiguous. Ergo it has two methods, -array and -set.
And/or, the -array and -set methods return proxies to what are likely the same or similar classes used internally. So in a functional sense they're a little different - those proxies will see mutations made on the original NSOrderedSet. -allObjects on the other hand does not - it genuinely creates an independent array, since its internal storage is likely a hashtable or similar that isn't readily proxied.
While there are other differences†, .allObjects does not imply a definite ordering, and .array does; and that's exactly what you are getting.
† .array returns a live proxy of the underlying NSOrderedSet, and if the underlying ordered set changes, the proxy will change with it.
Also... The NSArray returned by 'allObjects' is a copy of the values in the set.
But the NSArray returned by 'array' is a proxy of the objects in the set.
Thus if you change the value of any object in the set, you will change the value of the object in the array. A copy of the ordered set is not being made. So the two properties have different names because they do different things.

How to remove only one instance of an object from an NSMutableArray?

The Apple documentation says that the - (void)removeObject:(id)anObject method removes all occurrences of the given object from an NSMutableArray.
Is there a way to remove only one occurrence of the object from the array?
If you have a particular instance that you want removed, which has a unique memory address but would otherwise compare equal to other instances, you would use removeObjectIdenticalTo:.
If you want to remove the first object in the array that fits the bill, use indexOfObject:, which finds the lowest index, followed by removeObjectAtIndex: You can also use indexesOfObjectsPassingTest: to get the list of all indexes that contain equal objects, as an NSIndexSet, and then pick one out from there -- perhaps lastIndex, e.g.
It is really simple:
[yourArray removeObjectAtIndex:[yourArray indexOfObject:yourObject]]
Yes, you want to find the index of the specific object you want to remove and call:
- (void)removeObjectAtIndex:(NSUInteger)index
See the Apple documentation for NSMutableArray here.

"NSSet allObjects" does random ordering?

I have the following code:
self.temporaryImageArray = [(NSSet *)[[array objectAtIndex:0] images] allObjects]
Array holds an Band object from my CoreData model. It has an NSSet as a property called "images".
Now I use this temporaryImageArray to determine via timestamps whether or not the images need to be updated. I have come across some very random behavior and my question now is:
Does [NSSet allObjects] return the Objects from the Set randomly in no order?
Is there any way to prevent this or to have it return it in order? It would lessen the complexity of my code a lot.
NSSet is an unordered collection. It has no idea what the "order" of its objects are. Therefore, when you call -allObjects, it returns them unordered.
Note that the documentation on -allObjects states:
An array containing the set’s members, or an empty array if the set has no members. The order of the objects in the array isn’t defined.
(emphasis mine)
A set does not have order. However, in 10.7 (Lion), there is an NSOrderedSet class. This isn't available in iOS 4.0.
NSOrderedSet and NSMutableOrderedSet are now available in iOS 5 just so you're kept up to date.
Here's the link

Using sortUsingSelector on an NSMutableArray

I have used sortUsingSelector to sort an NSMutableArray of custom objects.
Now I'm trying to sort an NSMutableArray containing NSMutableArrays of custom objects.
Can you use sortUsingSelector on an NSMutableArray, or does it only work for custom classes?
If you can use blocks, the most straightforward way using sortUsingComparator:. Otherwise, you'll need to use sortUsingFunction:.
In either case, you are going to need to write a custom block or function that takes two arrays as arguments and returns a sort order based on their contents (I'm not sure what logic you are using to determine if array A or array B is "before" or "after" the other).
You'd do something like:
static NSInteger MySorterFunc(id leftArray, id rightArray, void *context) {
... return ascending/descending/same based on leftArray vs. rightArray ...
}
Then:
[myArrayOfArrays sortUsingFunction: MySorterFunc context: NULL];
It sends the selector to the objects, so you'll need to use one of the other sorters. Probably sortUsingFunction:context:.
Of course you can also use sortUsingSelector:, it really doesn’t matter whats the object in your array as long as it responds to the selector you want to use. But NSMutableArray and NSArray don’t have any comparison methods themselves, so you’d have to extend them using a category to implement your compare method.
So you probably want to use the other sorting methods pointed out in the other answers here. It’s not impossible to use sortUsingSelector: but it is rather inconvenient and most people (including me) would argue that it’s bad style to write a category for that.

Objective-C implementation of a histogram or bag datastructure

Instead of implementing my own I was wondering if anyone knows of a histogram or bag datastructure implementation in Objective-C that I can use.
Essentially a histogram is a hashmap of lists where the lists contain values that relate to their hash entry. A good example is a histogram of supermarket items where you place each group of items dairy, meat, canned goods in their own bag. You can then very easily access each group of items according to their type.
NSCountedSet is a multiset (aka "bag") that counts distinct objects, but doesn't allow duplicates. However, based on your explanation, I don't think that's what you need, and neither is a histogram, which automatically buckets values based on a set of (usually numerical) ranges.
I believe what you really want is a multimap, which is a "key to one-or-more values" relation. The data structures framework I maintain includes CHMultiDictionary, a multimap implementation. I won't claim by any means that it's perfect or complete, but I hope it may be helpful for your problem.
It sounds to me like you simply want a dictionary of arrays. You can put NSArrays as elements of NSDictionarys, something like:
NSMutableDictionary* dict = [NSMutableDictionary dictionary];
[dict setObject:[NSMutableArray arrayWithObjects:#"milk", #"eggs", #"cheese", nil] forKey:#"dairy"];
[dict setObject:[NSMutableArray arrayWithObjects:#"steak", #"sausages", #"mince", nil] forKey:#"meat"];
[[dict objectForKey:#"meat"] addObject:#"lamb"];
NSLog( #"Dictionary is %#", dict );
There's one in the GNU Objective-C Class library, but the docs appear to be pretty incomplete and the project's homepage must be currently having a problem -- still, if GPL software is acceptable for your project, you might want to download and check the sources.
CFIOMultimap apparently is an implementation of a multimap. However, as of the time of writing I couldn't get it to work. It returns nils all the time when I subscript.
Perhaps it can be fixed and adapted for your use.