Получение уникальных предметов из NSMutableArray - PullRequest
13 голосов
/ 04 июня 2010

У меня есть вопрос о Objective-C сегодня с NSMutableArray. Исходя из .net / c # фона у меня возникли некоторые проблемы при работе с этими вещами.

Допустим, у меня есть объект под названием "Песня"

Моя песня имеет 3 свойства:

  • Название
  • Исполнитель
  • Жанр

У меня есть NSMutableArray или NSArray, который содержит все мои объекты Song.

Как бы я попытался «запросить» мой массив, чтобы получить новый массив только с (уникальными) исполнителями или жанрами.

Где, как и в .net, вы могли бы написать простой запрос LINQ с предложением DISTINCT, как можно было бы решить это в Objective-C? Я предполагаю с предикатами, но изо всех сил пытаюсь найти решение.

Заранее спасибо.

Ответы [ 6 ]

36 голосов
/ 04 июня 2010

Вы также можете использовать:

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

Аналогичным образом, если вам нужно сравнить весь объект, вы можете создать новое свойство только для чтения, в котором динамически объединяются значения, с которыми вы хотите сопоставить (через хэш или иным образом), и сравнивать это с *: 1004 *

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

ПРИМЕЧАНИЕ: Имейте в виду, что это возвращает уникальные значения для указанного свойства, а не сами объекты. Так что это будет массив значений NSString, а не значений Song.

13 голосов
/ 04 июня 2010

В зависимости от того, что вы подразумеваете под «уникальными художниками», есть несколько разных решений. Если вы просто хотите получить всех артистов и не хотите, чтобы кто-либо появлялся более одного раза, просто сделайте [NSSet setWithArray:[songArray valueForKey:@"artist"]]. Если вы хотите установить список всех песен, являющихся единственной песней их исполнителя, вам нужно сначала найти исполнителей, которые исполняют только одну песню, а затем найти песни этих исполнителей:

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];
5 голосов
/ 08 августа 2013

Или вот так:

filterTags  = [[NSSet setWithArray:filterTags] allObjects];

filterTags сначала не был уникальным, но становится уникальным после операции.

3 голосов
/ 03 апреля 2015

Используйте NSOrderedSet вместо NSSet.

NSOrderedSet *uniqueOrderedSet = [NSOrderedSet setWithArray:itemsArray];
[itemsArray removeAllObjects];
[itemsArray addObjectsFromArray:[uniqueOrderedSet allObjects]];
3 голосов
/ 03 марта 2011

Это может быть неприменимо, но это решение для создания уникального набора значений ... Предположим, у вас есть массив событий NSMutable, которые имеют несколько повторяющихся записей. Этот массив называется eventArray. Объект NSSet можно использовать для обрезки этого массива, а затем для повторного заполнения этого массива, как показано ниже ...

NSSet *uniqueEvents = [NSSet setWithArray:eventArray];

[eventArray removeAllObjects];

[eventArray addObjectsFromArray:[uniqueEvents allObjects]];
0 голосов
/ 06 марта 2013

Я создал простой API запросов для Objective-C, который значительно облегчает выполнение таких задач. Используя Linq-ObjectiveC, отличный метод, для поиска песен с уникальными исполнителями потребуется следующее:

NSArray* songsWithUniqueArtistists = [input distinct:^id(id song) {
    return [song artist];
}];

Возвращает список экземпляров песни, каждый с уникальным исполнителем.

...