Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting unique items from NSMutableArray

I have a question about Objective-C today involving NSMutableArray. Coming from a .net/c# background I'm having some trouble working with these things.

Let's say I have an object called "Song"

My song has 3 properties:

  • Title
  • Artist
  • Genre

I have a NSMutableArray or NSArray which holds all my Song objects.

How would I go about trying to 'query' my array to get a new array with only (Unique) Artists or Genre's.

Where as in .net you would write a simple LINQ query with a DISTINCT clause, how would one solve this in Objective-C? I'm guessing with predicates but am struggling to find a solution.

like image 460
Gidogeek Avatar asked Jun 03 '10 20:06

Gidogeek


People also ask

What is difference between NSArray and NSMutableArray?

The primary difference between NSArray and NSMutableArray is that a mutable array can be changed/modified after it has been allocated and initialized, whereas an immutable array, NSArray , cannot.

What is an NSArray?

An object representing a static ordered collection, for use instead of an Array constant in cases that require reference semantics.

What is NSMutableArray in Swift?

The NSMutableArray class declares the programmatic interface to objects that manage a modifiable array of objects. This class adds insertion and deletion operations to the basic array-handling behavior inherited from NSArray . NSMutableArray is “toll-free bridged” with its Core Foundation counterpart, CFMutableArray .


2 Answers

You could also use:

NSArray *uniqueArtists = [songs valueForKeyPath:@"@distinctUnionOfObjects.artist"];
NSArray *uniqueGenres = [songs valueForKeyPath:@"@distinctUnionOfObjects.genre"];

Likewise, if you need to compare the entire object you could create a new readonly property that combines the values you want to match on (via a hash or otherwise) dynamically and compare on that:

NSArray *array = [songs valueForKeyPath:@"@distinctUnionOfObjects.hash"];

NOTE: Keep in mind this returns the uniques values for the specified property, not the objects themselves. So it will be an array of NSString values, not Song values.

like image 152
Luke Avatar answered Oct 17 '22 06:10

Luke


Depending on what you mean by "unique artists," there are a couple of different solutions. If you just want to get all the artists and don't want any to appear more than once, just do [NSSet setWithArray:[songArray valueForKey:@"artist"]]. If you mean you want to set a list of all the songs which are the only song by their artist, you need to first find the artists who only do one song and then find the songs by those artists:

NSCountedSet *artistsWithCounts = [NSCountedSet setWithArray:[songArray valueForKey:@"artist"]];
NSMutableSet *uniqueArtists = [NSMutableSet set];
for (id artist in artistsWithCounts)
    if ([artistsWithCounts countForObject:artist] == 1])
        [uniqueArtists addObject:artist];
NSPredicate *findUniqueArtists = [NSPredicate predicateWithFormat:@"artist IN %@", uniqueArtists];
NSArray *songsWithUniqueArtists = [songArray filteredArrayUsingPredicate:findUniqueArtists];
like image 13
Chuck Avatar answered Oct 17 '22 06:10

Chuck