【问题标题】:Remove entries from NSMutableDictionary based on match on NSString value根据 NSString 值的匹配从 NSMutableDictionary 中删除条目
【发布时间】:2014-08-13 17:39:57
【问题描述】:

在对 Instagram API 进行网络调用后,我返回了一个带有以下键/值结构的 responseDictionary NSDictionary 委托:

{
data =     (
            {
        bio = "Los Angeles/Orange County Realtor\U00ae \n\U6d1b\U6749\U77f6\U623f\U5730\U4ea7\U7ecf\U7eaa\U4eba\nCall/Text/WhatsApp: (310) 717-1321\nEmail: Jxxxcom\nWeChat (\U5fae\U4fe1): xx";
        "full_name" = "xx yy (\U7530\U4f73\U6dfc) Rx Realty";
        id = 25354408;
        "profile_picture" = "http://scontent-a.cdninstagram.com/hphotos-xpa1/outbound-distillery/t0.0-20/OBPTH/profiles/profile_xxx_75sq_1391378894.jpg";
        username = jxxi;
        website = "http://www.Jxghty.com";
    },

profile_picture 键通常有一个 NSString 值,其中包含anonymousUser(对于没有设置任何个人资料图片的用户)。

我希望从我的 responseDictionary 中删除这些条目,如下所示:

        //Create mutable copy of IG responseDictionary
        NSMutableDictionary *dictCleanAvatars = [responseDictionary mutableCopy];
        NSLog(@"Log dictCleanAvatars after mutableCopy IG response: %@", dictCleanAvatars);

        NSArray *keys = [dictCleanAvatars allKeys]; //get all the keys
        NSUInteger k2 = [dictCleanAvatars count];
        NSLog(@"k2 in dictCleanAvatars before cleanup is: %lu", (unsigned long)k2);

        for (int i = 0; i<k2; i++)
        {

            if ([[dictCleanAvatars objectForKey:[keys objectAtIndex:i]] isKindOfClass:[NSString class]])
            {
                //if its an NSString - don't want an exception if its another type of object
                NSLog(@"Yes, objectAtIndex:i us Kind ofClass NSString for i = %d", i);

                if ([[dictCleanAvatars objectForKey:[keys objectAtIndex:i]] rangeOfString:@"anonymousUser"].location != NSNotFound)
                {
                    NSLog(@"Yes, anonymousUser identified in objectAtIndex:i for i = %d", i);
                    //if object has the key word im looking for
                    [dictCleanAvatars removeObjectForKey:[keys objectAtIndex:i]]; //remove the key
                    NSLog(@"That's dictCleanAvatars after loop %d: %@", i, dictCleanAvatars);
                }
            }
        }

但这不起作用。

会重视更多经验丰富的 iOS 开发者的反馈。

【问题讨论】:

  • “但这不起作用”不是对问题的描述。
  • 为什么不使用 KVC 来查找和删除您的密钥之类的数据。字典.valueForKey(@"data.Anonymous") ?然后尝试使用相同的路径进行删除

标签: ios objective-c nsstring nsmutabledictionary


【解决方案1】:

如果您尝试构建一个包含 data 键数组中的所有内容的数组,但忽略 profile_picture 包含字符串“AnonymousUser”的那些字典,您可以使用 NSPredicate

NSArray *dataArray = responseDictionary[@"data"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"not (profile_picture contains 'AnonymousUser')"];
NSArray *filteredArray = [dataArray filteredArrayUsingPredicate:predicate];

或者你可以使用predicateWithBlock:

NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(NSDictionary *evaluatedObject, NSDictionary *bindings) {
    return [evaluatedObject[@"profile_picture"] rangeOfString:@"AnonymousUser"].location == NSNotFound;
}];

顺便说一句,如果您已经有一个可变数组,您还可以使用filterUsingPredicate 从中删除条目,使用上述谓词:

NSMutableArray *mutableDataArray = [responseDictionary[@"data"] mutableCopy];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"not (profile_picture contains 'AnonymousUser')"];
[mutableDataArray filterUsingPredicate:predicate];

另一方面,如果您不想从字典数组中删除整个字典,而是想简单地删除出现“AnonymousUser”的profile_picture,则需要确保不仅数组是可变的,它的组成字典也是可变的。

最简单的方法是在解析 JSON 时指定 NSJSONReadingMutableContainers 选项。然后,您可以遍历 NSMutableDictionary 条目,删除带有 profile_picture 和“AnonymousUser”的 profile_picture 条目:

NSMutableDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingMutableContainers error:&error];
NSMutableArray *mutableDataArray = responseDictionary[@"data"];

for (NSMutableDictionary *dictionary in mutableDataArray) {
    NSString *profilePicture = dictionary[@"profile_picture"];
    if ([profilePicture rangeOfString:@"AnonymousUser"].location != NSNotFound) {
        [dictionary removeObjectForKey:@"profile_picture"];
    }
}

但是,如果您在解析 JSON 时无法指定 NSJSONReadingMutableContainers 选项并且卡在不可变集合中,则需要制作它的可变副本。不幸的是,数组的简单 mutableCopy 不会使成员字典本身可变,但您可以使用 Core Foundation 对 CFPropertyListCreateDeepCopy 的调用来创建具有可变条目的可变数组,然后您可以对其进行修改:

NSMutableArray *mutableDataArray = CFBridgingRelease(CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFArrayRef)responseDictionary[@"data"], kCFPropertyListMutableContainers));

然后你可以使用上面的for循环,遍历这个数组的字典条目,删除有问题的profile_picture条目。

【讨论】:

  • 嗨 Rob:我选择了第三个选项。喜欢简洁。
【解决方案2】:
if [[dictCleanAvatars objectForKey:[keys objectAtIndex:i]] isEqualToString@"anonymousUser"] {

问题是,假设 [dictCleanAvatars objectForKey:[keys objectAtIndex:i]] 不是 NSString?您可能需要先检查一下。

【讨论】:

    【解决方案3】:

    如果您正在查看的唯一字段是 profile_picture,我会采用一种不太通用的方法,这种方法更具可读性和可理解性

    此代码适用于我

    - (void)testExample
    {
        NSDictionary *dictionary = @{ @"data": @[ @{ @"bio": @"blah blah", @"profile_picture": @"some stuff anonymousUser other stuff" },
                                                  @{ @"bio": @"some other object", @"profile_picture": @"some other profile picture link" }] };
        // dictionary is a mock of the data you provided
    
        NSArray *data = [dictionary objectForKey:@"data"];
        for (NSDictionary * avatarDict in data) {
            NSMutableDictionary *mdict = [avatarDict mutableCopy];
            id ppid = [mdict objectForKey:@"profile_picture"];
            if ([ppid isKindOfClass:[NSString class]]) {
                NSString *pp = (NSString *)ppid;
                if ([pp rangeOfString:@"anonymousUser"].location != NSNotFound) {
                    [mdict removeObjectForKey:@"profile_picture"];
                }
            }
            NSLog(@"altered dictionary: %@", mdict);
        }
    }
    

    输出:

    2014-08-13 10:53:36.727 test[11981:60b] altered dictionary: {
        bio = "blah blah";
    }
    2014-08-13 10:53:36.728 test[11981:60b] altered dictionary: {
        bio = "some other object";
        "profile_picture" = "some other profile picture link";
    }
    

    【讨论】:

    • 那不只是从字典副本中删除条目吗?
    • 是的,他不能从不可变的原始文件中删除它。
    猜你喜欢
    • 2015-05-08
    • 2013-02-16
    • 1970-01-01
    • 2022-08-03
    • 1970-01-01
    • 2019-02-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多