如何重命名NSMutableDictionary中的键?

11
我有一个 NSMutableDictionary,我需要在我的代码中将字典中的任何 Key 动态重命名为新值。 我找不到任何内置的API来完成这个操作。如何实现?是否有可用的内置API?谢谢大家。

将值复制出来,然后创建一个新的键并赋予所需的名称是一种选择吗? - Jumhyn
我无法直接编辑现有的键? - EmptyStack
4个回答

38
// assumes that olkdey and newkey won't be the same; they can't as
// constants... but...
[dict setObject: [dict objectForKey: @"oldkey"] forKey: @"newkey"];
[dict removeObjectForKey: @"oldkey"];

想一下"直接编辑现有键"是什么意思。字典是一个哈希表;它将键的内容进行哈希以查找值。

如果您更改键的内容会发生什么?该键需要重新哈希(并且需要重新平衡字典的内部结构),否则该值将无法检索。

首先,为什么要编辑键的内容?也就是说,这解决了什么问题,而上述方法没有解决?


谢谢。这很好。我不能直接编辑现有的键吗? - EmptyStack
嗯.. 没有具体的要求.. 我只是希望有一种直接编辑密钥的方法.. 就这样.. 谢谢啊.. - EmptyStack
谢谢@bbum,这对于NSUserdefault也起作用了! - Douglas
如果 oldkey 等于 newkey,则此操作将失败。 - de.
在这个例子中,它不会失败,因为它们不是变量。但值得注意的是! - bbum

9
这应该是有效的:
- (void) renameKey:(id<NSCopying>)oldKey toKey:(id<NSCopying>)newKey{
    NSObject *object = [dictionary objectForKey:oldKey];
    [object retain];
    [dictionary removeObjectForKey:oldKey];
    [dictionary setObject:object forKey:newKey];
    [object release];
}

这与bbum的答案完全相同,但是,如果您首先删除旧密钥(就像在此示例中一样),则必须暂时保留对象,否则可能会被释放掉。

结论:除非您明确需要先删除旧密钥,否则请按照bbum的方法操作。


1
这也更具有防御性和通用性;如果oldKey和newKey是相同的字符串,它仍然可以运行(尽管会做一些额外的工作)。 - bbum

5
@interface NSMutableDictionary (KAKeyRenaming)
- (void)ka_replaceKey:(id)oldKey withKey:(id)newKey;
@end

@implementation NSMutableDictionary (KAKeyRenaming)
- (void)ka_replaceKey:(id)oldKey withKey:(id)newKey
{
    id value = [self objectForKey:oldKey];
    if (value) {
        [self setObject:value forKey:newKey];
        [self removeObjectForKey:oldKey];
    }
}
@end

这也很好地处理了字典没有键值的情况。

1
另一个不错的解决方案;但是请为这些方法添加一些不太通用且可能会与将来框架的某些新增发生冲突的前缀,如果有的话... - bbum
1
@bbum是正确的:自定义类和协议的前缀应被视为一项要求。为了完美起见进行了编辑。 - Costique
1
类别名称并不重要;在运行时不可用。你需要担心的是方法名称... - bbum
当旧键和新键相同时,会得到什么结果。这可能听起来像一个愚蠢的问题,但不幸的是,我遇到了类似的情况。在某些情况下,键是相同的,字符串的大小写(大写、小写或组合)有所不同。我从服务器获取密钥,不能保证两者都不同,而且移动客户端也应该准备处理这种情况。如果您对此情况有解决方案,请发表评论。 - Dinakar

0

我必须遍历一个完整的JSON响应对象,其中包含字段、子字典和子数组。这是因为JSON字段之一被称为“return”,它是iOS保留字,因此不能与JSONModel Cocoa Pod一起使用。 以下是代码:

+ (id) sanitizeJSON:(id) dictIn {
if (dictIn) //check not null
{
    // if it's a dictionary item
    if ([dictIn isKindOfClass:[NSDictionary class]])
    {
        NSMutableDictionary *dictOut = [dictIn mutableCopy]; 
        // Do the fix replace "return" with "not_return"
        if ([dictOut objectForKey: @"return"])
        {[dictOut setObject: [dictIn objectForKey: @"return"] forKey: @"not_return"];
         [dictOut removeObjectForKey: @"return"];}

        // Continue the recursive walk through
        NSArray*keys=[dictOut allKeys]; //get all the keys
        for (int n=0;n<keys.count;n++)
        {
           NSString *key = [keys objectAtIndex:n];
           //NSLog(@"key=%@ value=%@", key, [dictOut objectForKey:key]);
           if (([[dictOut objectForKey:key] isKindOfClass:[NSDictionary class]]) || ([[dictOut objectForKey:key] isKindOfClass:[NSArray class]]))
            {
                // recursive call
                id sanitizedObject =  [self sanitizeJSON:[dictOut objectForKey:key]];
                [dictOut removeObjectForKey: key];
                [dictOut setObject:sanitizedObject forKey:key];
                // replace returned (poss modified) item with this one
            }
        }
        return dictOut; //return dict
    }
    else if ([dictIn isKindOfClass:[NSArray class]]) //Or if it's an array item
    {

        NSMutableArray *tempArray = [dictIn mutableCopy];
        // Do the recursive walk across the array
        for (int n=0;n< tempArray.count; n++)
        {
            // if array item is dictionary
            if (([[tempArray objectAtIndex:n] isKindOfClass:[NSDictionary class]]) || ([[tempArray objectAtIndex:n] isKindOfClass:[NSArray class]]))
            {
                // recursive call
                id sanitizedObject =  [self sanitizeJSON:[tempArray objectAtIndex:n]];
                // replace with the possibly modified item
                [tempArray replaceObjectAtIndex:n withObject:sanitizedObject];
            }
        }
        return tempArray; //return array
    }
    return dictIn; //Not nil or dict or array
}
else
  return dictIn; //return nil 
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接