按键将 NSArray 分成排序的组

Breaking NSArray into sorted groups by key

这里是菜鸟,需要一些帮助。

我有一个 NSArray,里面装满了我需要按专辑随机播放的 MPMediaItems(歌曲)。我最终需要做的事情:

1) 按专辑对曲目进行分组(专辑总数未知)。

2) 按曲目编号对专辑中的曲目进行排序。

3) Return 一个包含所有曲目的新数组(按组随机排列,仍然按组内的编号排序)。

我相信我知道如何通过一遍又一遍地遍历数组来做到这一点,但这似乎非常低效。我怀疑 NSDictionary 可能是更好的选择,但我什至不知道从哪里开始。

任何帮助将不胜感激!

迈克

尽管我没有使用过 MPMediaItems,但我可以解释 NSArray 的排序和过滤是多么简单。

出于说明的目的,我正在创建一个名为 Song 的虚构 class,它可能与 MPMediaItem 不同。 Song class 有两个属性,分别是 albumName 和 trackNumber。然后我们添加一个名为 + (NSDictionary *)songsGroupedByAlbumAndSortedByTrack:(NSArray *)songs 的 class 方法,它将接受一个 Song 对象数组和 returns 一个 NSDictionary。返回字典中的每个键都将是一个专辑名称,对应的值将是属于该专辑并按曲目编号排序的歌曲数组。

@interface Song : NSObject

@property (nonatomic, copy) NSString *albumName;
@property (nonatomic, assign) NSInteger trackNumber;

@end

@implementation Song

+ (NSDictionary *)songsGroupedByAlbumAndSortedByTrack:(NSArray *)songs {

    NSSortDescriptor *byTrack = [NSSortDescriptor sortDescriptorWithKey:@"trackNumber" ascending:YES];
    NSArray *albumNames = [songs valueForKeyPath:@"@distinctUnionOfObjects.albumName"];
    NSMutableDictionary *groupedByAlbumAndSortedByTrack = [[NSMutableDictionary alloc] init];
    for (NSString *album in albumNames) {
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"albumName == %@",album];
        NSArray *currentAlbumSongs = [songs filteredArrayUsingPredicate:predicate];
        NSArray *currentAlbumSongsSortedByTrack = [currentAlbumSongs sortedArrayUsingDescriptors:@[byTrack]];
        [groupedByAlbumAndSortedByTrack setObject:currentAlbumSongsSortedByTrack forKey:album];
    }
    return groupedByAlbumAndSortedByTrack;
}

@end

通过使用 NSSortDescriptor 进行排序并使用 NSPredicate 进行过滤,我们消除了数组中的大量循环。

第一步是从我们使用 KVC collectionOperator @distinctUnionOfObjects 完成的歌曲数组中提取专辑名称。

然后我们遍历专辑名称数组并将属于该专辑的所有歌曲添加到 NSArray。

上面给出的示例代码是对NSArray的一般排序和过滤。 快速浏览 MPMediaItem class 参考资料可以看出,Apple 已经提供了很多用于操作 mediaItems 的方法。请看一下MPMediaPropertyPredicate