带有数组的 nsdictionary nspredicate 过滤

Posted

技术标签:

【中文标题】带有数组的 nsdictionary nspredicate 过滤【英文标题】:nsdictionary with arrays nspredicate filtering 【发布时间】:2015-01-19 16:40:33 【问题描述】:

我有一个表格视图,我想通过可搜索的方式进行搜索。它以前可以工作,但是当我添加部分时,我遇到了麻烦,因为我必须从数组更改为字典。

所以基本上我有一个看起来像这样的 NSDictionary

 @"districtA": array with point objects, @"districtB": array with point objects

我需要根据数组中的点 objects.name 过滤它们。之后,我想创建一个包含过滤对象的新 nsdictionary。

我尝试了至少 10 种不同的方法,但我无法弄清楚,所以我认为这是我最积极的唯一方法。 这是我能想到的唯一方法,如果有更简单的方法或更逻辑的方法,请告诉我。

-(void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope 

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.name BEGINSWITH[c] %@",searchText];

//create new array to fill
NSArray *arrayWithFilteredPoints = [[NSArray alloc] init];

//loop through the values and put into an rray based on the predicate
arrayWithFilteredPoints = [NSArray arrayWithObject:[[self.PointList allValues] filteredArrayUsingPredicate:predicate]];

NSMutableDictionary *dict = [@ mutableCopy];

for (Point *point in arrayWithFilteredPoints) 
    if (![dict objectForKey:Point.district])
        dict[Point.district] = [@[] mutableCopy];
        [dict[Point.district]addObject:Point];


self.filteredPointList = dict;
self.filteredDistrictSectionNames = [[dict allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];

这会导致崩溃,它当然发生在使用谓词的地方,但我不知道如何调试我应该使用什么谓词:

on 'NSInvalidArgumentException', reason: 'Can't do a substring operation with something that isn't a string (lhs = (
West ) rhs = w)'

【问题讨论】:

【参考方案1】:

我已经阅读了 cmets,你是对的。我的代码有问题。

我更改了逻辑,我添加了更多步骤(例如创建不需要它的 NSArray)以使解决方案清晰

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.name BEGINSWITH[c] %@",searchText];

//1. create new array to fill only the Points from the dictionary
NSArray *allPoints = [self.PointList allValues];
NSMutableArray *allPointObjects = [[NSMutableArray alloc]init];

for (NSArray *array in allPoints) 
    for (Point *point in array) 
        [allPointObjects addObject:point];
    


//2. loop through allPointObjects and put into an mutablearray based on the predicate
NSArray *arrayWithFilteredPoints = [[NSArray alloc] init];
arrayWithFilteredPoints = [allPointObjects filteredArrayUsingPredicate:predicate];

NSMutableDictionary *dict = [@ mutableCopy];

for (Point *point in arrayWithFilteredPoints) 
    if (![dict objectForKey:point.district])
        dict[point.district] = [@[] mutableCopy];
        [dict[point.district]addObject:Point];


self.filteredPointList = dict;
self.filteredDistrictSectionNames = [[dict allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];

最后我想要一个过滤的 nsdictionary,我可以将它传回我的 tableview,它根据键(区)读取字典对象

【讨论】:

【参考方案2】:

您的描述似乎很清楚[self.PointList allValues] 不是Point 对象数组,而是Point 对象数组数组。这就是你的困难的根源,包括你最初的崩溃。

您需要决定如何处理;例如,如果您只想要一个大的 Point 对象数组,则在过滤之前将数组数组展平。我无法进一步建议您,因为对我来说您想要的最终结果并不明显。

编辑您现在已经修改了代码,我可以更清楚地看到您要做什么。您有一个字典,其值是点数组,并且您试图从每个数组中过滤出一些点。我会做的是 that - 即,通过键运行,提取每个数组,过滤它,然后将其放回(如果数组现在为空,则删除键)。但是我可以看到你所做的应该是可行的,因为你巧妙地将键放在开始的点中,所以你可以从中重建字典结构。

【讨论】:

这让我思考并改变了逻辑,它有效并且更容易理解。检查这是否是正确的方法.. 我还添加了我想要的以及我想要的原因 是的,看起来更好。 :) 这不是我会做的——你正在丢失原来的字典键——但我想它是有效的,因为这些点也包含这些键作为它们的district。我会做的是提取每个键的值数组,过滤它,然后再放回去。

以上是关于带有数组的 nsdictionary nspredicate 过滤的主要内容,如果未能解决你的问题,请参考以下文章

如何将带有对象数组的 json 字符串转换为带有 nsdictionaries 的 nsarray - IOS

使用带有数组的 NSDictionary 创建 JSON 文件

如何从 NSDictionary 中删除对象

获取按其各自值排序的 NSDictionary 键

带有 NSArray 的 UITableview 包含 NSDictionary 和 NSDictionary 包含另一个 NSDictionary

iOS NSDictionary 保存到 NSUserDefaults 不保存值