Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/36.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 如何就地交换`NSMutableDictionary`键和值?_Iphone_Ios_Nsmutabledictionary - Fatal编程技术网

Iphone 如何就地交换`NSMutableDictionary`键和值?

Iphone 如何就地交换`NSMutableDictionary`键和值?,iphone,ios,nsmutabledictionary,Iphone,Ios,Nsmutabledictionary,我有一个NSMutableDictionary,我想交换值和键。i、 e,交换值后,值变为键,其对应的键变为值,所有键和值都是唯一的。正在寻找就地解决方案,因为规模非常大。另外,键和值是NSStringobjectsEDIT:我写了几行代码,让OP开始创建自己的算法。答案不太受欢迎,所以我精心设计了一个算法的完整实现,可以满足他的要求,并且更进一步 优点: 对字典的内容不做任何假设,例如,值不需要符合“NSCopying”协议 跨越集合的整个层次结构,交换所有键 它很快,因为它使用递归和快速枚

我有一个
NSMutableDictionary
,我想交换值和键。i、 e,交换值后,值变为键,其对应的键变为值,所有键和值都是唯一的。正在寻找就地解决方案,因为规模非常大。另外,键和值是
NSString
objects

EDIT:我写了几行代码,让OP开始创建自己的算法。答案不太受欢迎,所以我精心设计了一个算法的完整实现,可以满足他的要求,并且更进一步

优点:

  • 对字典的内容不做任何假设,例如,值不需要符合“NSCopying”协议
  • 跨越集合的整个层次结构,交换所有键
  • 它很快,因为它使用递归和快速枚举
  • 它不会改变原有词典的内容,而是创建了一个全新的词典
代码已通过两个集合的类别实现:

@interface NSDictionary (Swapping)

- (NSDictionary *)dictionaryBySwappingKeyWithValue;

@end

@interface NSDictionary (Swapping)

- (NSDictionary *)dictionaryBySwappingKeyWithValue
{
    NSMutableDictionary *mutableDictionary = [NSMutableDictionary dictionaryWithCapacity:self.count];

    [self enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {
        id newKey = nil;
        if ([value isKindOfClass:[NSDictionary class]]) {
            newKey = [value dictionaryBySwappingKeyWithValue];

        } else if ([value isKindOfClass:[NSArray class]]) {
            newKey = [value arrayBySwappingKeyWithValue];
        } else {
            newKey = value;
        }

        if (![newKey conformsToProtocol:@protocol(NSCopying)]) {
            newKey = [NSValue valueWithNonretainedObject:newKey];
        }

        mutableDictionary[newKey] = key;
    }];

    return [NSDictionary dictionaryWithDictionary:mutableDictionary];
}

@end
而且

@interface NSArray (Swapping)

- (NSArray *)arrayBySwappingKeyWithValue;

@end

@implementation NSArray (Swapping)

- (NSArray *)arrayBySwappingKeyWithValue
{
    NSMutableArray *mutableArray = [NSMutableArray arrayWithCapacity:self.count];

    [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        if ([obj isKindOfClass:[NSDictionary class]]) {
            NSDictionary *newDict = [obj dictionaryBySwappingKeyWithValue];
            mutableArray[idx] = newDict;
        } else if ([obj isKindOfClass:[NSArray class]]) {
            NSArray *newArray = [obj arrayBySwappingKeyWithValue];
            mutableArray[idx] = newArray;
        } else {
            mutableArray[idx] = obj;
        }
    }];

    return [NSArray arrayWithArray:mutableArray];
}

@end
例如,假设您有一个具有以下结构的词典:

UIView *view = [[UIView alloc] init];
NSDictionary *dict = @{@"1" : @"a",
                       @"2" : @[ @{ @"5" : @"b" } ],
                       @"3" : @{@"6" : @"c"},
                       @"7" : view};

NSDictionary *newDict = [dict dictionaryBySwappingKeyWithValue];
在控制台中打印
newDict
对象将提供以下输出:

(lldb) po mutableDictionary
{
    a = 1;
    ({b = 5;}) = 2;
    {c = 6;} = 3;
    "<30b50617>" = 7; 
}
(lldb)po可变字典
{
a=1;
({b=5;})=2;
{c=6;}=3;
"" = 7; 
}
如您所见,不仅在层次结构的第一级交换了键和值,而且在每个集合的深处交换了键和值

表示包装在NSValue中的UIView对象。由于UIView不符合NSCopying协议,因此如果希望它成为集合中的密钥,则需要以这种方式处理它

注意:代码在几分钟内完成。如果我错过了什么,请告诉我

NSMutableDictionary *d = [NSMutableDictionary dictionaryWithDictionary:@{
                             @"key1" : @"value1",
                             @"key2" : @"value2"}];

for (NSString *key in [d allKeys]) {
    d[d[key]] = key;
    [d removeObjectForKey:key];
}

NSLog(@"%@", d); // => { value1 : key1,
                 //      value2 : key2 }

假设
  • 唯一值(因为它们将成为键)
  • 值符合
    NSCopying
    (同上)
  • 没有值等于任何键(否则冲突名称将在过程中丢失)
假设: 无键=值

复杂性:
不需要额外的空间。将循环一次并替换所有键值对。

这里是反转字典的另一种方法。对我来说最简单的

NSArray *keys = dictionary.allKeys;
NSArray *values = [dictionary objectsForKeys:keys notFoundMarker:[NSNull null]];
[dictionary removeAllObjects]; // In case of huge data sets release the contents.
NSDictionary *invertedDictionary = [NSDictionary dictionaryWithObjects:keys forKeys:values];
[dictionary setDictionary:invertedDictionary]; // In case you want to use the original dictionary.


我没有通读所有的代码,但它看起来像是对任务的过度杀伤力。它没有到位,因为OP askedYou可能打算用allValues交换ALLKEY?在任何情况下,
allValues
返回的元素顺序都没有定义,因此这可能会与错误的元素相关联。如果一个键与另一个(或任何)键的值相同,这将不起作用。@Jim当然,但是OP保证了问题中的key/valye唯一性。我认为您不想在对集合进行迭代时修改集合。枚举的集合是
[d allkey]
,在枚举过程中不会发生变异。@pedro.m,OP声明它们是
NSString
,因此,它符合
NSCopying
是否可以保证没有复制值的键,反之亦然?是的,键是自动生成的id,值是字符串。-1这甚至不编译
getObjectForKey
不存在,您不能像那样循环浏览字典。也就是说,即使你修正了明显的错误,核心概念它与公认的答案是相同的,因此它不会增加任何价值。@GabrielePetronella只是一个细节:你可以像这样循环浏览字典。@GabrielePetronella很抱歉,我忘了它的objectForKey。我可以循环使用for(NSStrig*key in myDictionary)的字典,其中myDictionary是一个有效的字典。@iMartin是的,我不好,即使在迭代集合时对集合进行变异仍然是一个坏主意。@GabrielePetronella True,他缺少
-copy
。与其他许多答案一样,它没有抓住要点:它没有到位。@GabrielePetronella抱歉。但如果您有性能或内存问题,也许您可以使用
-allKeysForObject:
进行反向查找。没有分配,没有复制。问题不是我,是OP需要它。@GabrielePetronella,我明白了。我对“就地”的理解略有不同。最后,如果您执行
[d setDictionary:invertaddictionary]是否已安装到位?:)不完全是这样,因为您正在分配额外的内存来创建
invertaddictionary
,而这正是OP不想要的。
for (NSString *key in [myDictionary allKeys]) {
     NSString *value = [responseDataDic objectForKey:key];
     [myDictionary removeObjectForKey:key];
     [myDictionary addObject:key forKey:value];
}
NSArray *keys = dictionary.allKeys;
NSArray *values = [dictionary objectsForKeys:keys notFoundMarker:[NSNull null]];
[dictionary removeAllObjects]; // In case of huge data sets release the contents.
NSDictionary *invertedDictionary = [NSDictionary dictionaryWithObjects:keys forKeys:values];
[dictionary setDictionary:invertedDictionary]; // In case you want to use the original dictionary.