我们有一个应用程序调用SOAP Web服务并检索XML的长列表,然后应用程序将其解析为NSArray
个NSDictionary
个对象。 NSArray
包含租赁公寓信息列表,每个信息都存储在NSDictionary
中。
整个列表可能包含10种不同类型的公寓(即2室,3室),我们需要根据Room-Type将NSArray
拆分为较小的NSArray
,其中在NSDictionary
个对象中有关键的“roomType”。
目前我们的算法是
[NSArray valueForKeyPath:@"@distinctUnionofObjects.room-type"]
获取一个独特的房间类型值列表。NSPredicate
从原始列表我们的代码如下(为清晰起见重命名):
NSArray *arrOriginal = ... ...; // Contains the Parsed XML list
NSMutableArray *marrApartmentsByRoomType = [NSMutableArray arrayWithCapacity:10];
NSMutableArray *arrRoomTypes = [arrOriginal valueForKeyPath:@"distinctUnionOfObjects.roomType"];
for(NSString *strRoomType in arrRoomTypes) {
NSPredicate *predicateRoomType = [NSPredicate predicateWithFormat:@"roomType=%@", strRoomType];
NSArray *arrApartmentsThatMatchRoomType = [arrOriginal filteredArrayUsingPredicate:predicateRoomType]; // TAKES A LONG TIME EACH LOOP-ROUND
[marrApartmentsByRoomType addObject:arrApartmentsThatMatchRoomType];
}
然而,步骤3花费很长时间,因为原始列表可能包含大量(> 100,000)的项目。似乎NSPredicate
遍历每个键值的整个列表。是否有更有效的方法可以根据NSArray
密钥将较大的NSArray
拆分为较小的NSDictionary
?
答案 0 :(得分:3)
如果您的分割数组的顺序不重要,我有一个解决方案:
NSArray *arrOriginal;
NSMutableDictionary *grouped = [[NSMutableDictionary alloc] initWithCapacity:arrOriginal.count];
for (NSDictionary *dict in arrOriginal) {
id key = [dict valueForKey:@"roomType"];
NSMutableArray *tmp = [grouped objectForKey:key];
if (tmp == nil) {
tmp = [[NSMutableArray alloc] init];
[grouped setObject:tmp forKey:key];
}
[tmp addObject:dict];
}
NSMutableArray *marrApartmentsByRoomType = [grouped allValues];
答案 1 :(得分:1)
这是非常高效的
- (NSDictionary *)groupObjectsInArray:(NSArray *)array byKey:(id <NSCopying> (^)(id item))keyForItemBlock
{
NSMutableDictionary *groupedItems = [NSMutableDictionary new];
for (id item in array) {
id <NSCopying> key = keyForItemBlock(item);
NSParameterAssert(key);
NSMutableArray *arrayForKey = groupedItems[key];
if (arrayForKey == nil) {
arrayForKey = [NSMutableArray new];
groupedItems[key] = arrayForKey;
}
[arrayForKey addObject:item];
}
return groupedItems;
}
答案 2 :(得分:0)
改善@Jonathan回答
维护与原始数组中相同的顺序
//only to a take unique keys. (key order should be maintained)
NSMutableArray *aMutableArray = [[NSMutableArray alloc]init];
NSMutableDictionary *dictFromArray = [NSMutableDictionary dictionary];
for (NSDictionary *eachDict in arrOriginal) {
//Collecting all unique key in order of initial array
NSString *eachKey = [eachDict objectForKey:@"roomType"];
if (![aMutableArray containsObject:eachKey]) {
[aMutableArray addObject:eachKey];
}
NSMutableArray *tmp = [grouped objectForKey:key];
tmp = [dictFromArray objectForKey:eachKey];
if (!tmp) {
tmp = [NSMutableArray array];
[dictFromArray setObject:tmp forKey:eachKey];
}
[tmp addObject:eachDict];
}
//NSLog(@"dictFromArray %@",dictFromArray);
//NSLog(@"Unique Keys :: %@",aMutableArray);
// 再次从字典转换为数组 ...
self.finalArray = [[NSMutableArray alloc]init];
for (NSString *uniqueKey in aMutableArray) {
NSDictionary *aUniqueKeyDict = @{@"groupKey":uniqueKey,@"featureValues":[dictFromArray objectForKey:uniqueKey]};
[self.finalArray addObject:aUniqueKeyDict];
}
希望,当客户希望最终数组与输入数组的顺序相同时,它会有所帮助。