原文:http://rypress.com/tutorials/objective-c/data-types/nsdictionary

NSDictionary

如同NSSet,NSDictionary类也是描述对象无序数据集;然而,但是由于有key的存在可以使得key和对象一一对应。

The basic collection classes of the Foundation Framework

NSDictionary是不可变的,但是NSMutableDictionary可以动态的增加好删除数据,是可变的。

创建不可变字典

不可变字典可以使用 @{}的语法来创建,也可以使用dictionaryWithObjectsAndKeys: 和dictionaryWithObjects:forKeys:方法进行创建,详见下述:

// Literal syntax
NSDictionary *inventory = @{
    ],
    ],
    ],
    ],
};
// Values and keys as arguments
inventory = [NSDictionary dictionaryWithObjectsAndKeys:
             [NSNumber numberWithInt:], @"Mercedes-Benz SLK250",
             [NSNumber numberWithInt:], @"Mercedes-Benz E350",
             [NSNumber numberWithInt:], @"BMW M3 Coupe",
             [NSNumber numberWithInt:], @"BMW X6", nil];
// Values and keys as arrays
NSArray *models = @[@"Mercedes-Benz SLK250", @"Mercedes-Benz E350",
                    @"BMW M3 Coupe", @"BMW X6"];
NSArray *stock = @[[NSNumber numberWithInt:],
                   [NSNumber numberWithInt:],
                   [NSNumber numberWithInt:],
                   [NSNumber numberWithInt:]];
inventory = [NSDictionary dictionaryWithObjects:stock forKeys:models];
NSLog(@"%@", inventory);

dictionaryWithObjectsAndKeys:方法把键值对作为参数,所以每两个参数最为一个键值对。这样的排列显得很不直观,并且需要值在前键在后。dictionaryWithObjects:ForKeys:方法使用起来相对直观和简单一下,但是你要特别注意,键值的数组长度必须保持一致。

在平时我们可能使用NSString来做key,但是其实只要实现了NSCopying协议并且实现了hash和isEqual:方法的对象都可以做key。这是因为作为key的话其实会拷贝原值,而作为值的对象通常采用强引用的方式(这一点和set以及array一样)。

访问 Values and Keys

你可以使用像arrays一样的下标的方式进行(someDict[key])某个key下value的读取。objectForKey:方法是另外一个比较常用的获取数据的方式。

NSDictionary *inventory = @{
    ],
    ],
    ],
    ],
};
NSLog(@"There are %@ X6's in stock", inventory[@"BMW X6"]);
NSLog(@"There are %@ E350's in stock",
      [inventory objectForKey:@"Mercedes-Benz E350"]);

一般我们都是按照上述方式进行数据的读取的;然而我们也可以使用allKeysForObject:反过来查询。注意这个方法返回的是一个数组因为会有多个key下的value是一样的。例如下面的例子。

NSDictionary *inventory = @{
    ],
    ],
    ],
    ],
};
NSArray *outOfStock = [inventory allKeysForObject:
                       [NSNumber numberWithInt:]];
NSLog(@"The following cars are currently out of stock: %@",
      [outOfStock componentsJoinedByString:@", "]);

枚举字典

如同sets和arrays一样快速枚举是去枚举字典的高效的方式,它通过key来循环访问整个字典。NSDictionary同样也提供了count方法来返回整个字典中存储的键值对。

NSDictionary *inventory = @{
    ],
    ],
    ],
    ],
};
NSLog(@"We currently have %ld models available", [inventory count]);
for (id key in inventory) {
    NSLog(@"There are %@ %@'s in stock", inventory[key], key);
}

你可以使用allKeys/allValues方法来讲字典的键值分离,并且这两个方法都返回对应key和value的数组,并且顺序是按照键值对一一对应的。

NSLog(@"Models: %@", [inventory allKeys]);
NSLog(@"Stock: %@", [inventory allValues]);

还有一种以块方式枚举的方式:

[inventory enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
    NSLog(@"There are %@ %@'s in stock", obj, key);
}];

字典比较

字典的比较和数组的比较一样的。当比较的字典一样(键值对和键值对数目都一样)的时候isEqualToDictionary:方法返回YES。

NSDictionary *warehouseInventory = @{
    ],
    ],
    ],
    ],
};
NSDictionary *showroomInventory = @{
    ],
    ],
    ],
    ],
};
if ([warehouseInventory isEqualToDictionary:showroomInventory]) {
    NSLog(@"Why are we storing so many cars in our showroom?");
}

字典keys的排序

字典无法排序到一个新的实例中,但是能够通过keysSortedByValueUsingComparator:方法来对key进行排序。

NSDictionary *prices = @{
    @"Mercedes-Benz SLK250" : [NSDecimalNumber decimalNumberWithString:@"42900.00"],
    @"Mercedes-Benz E350" : [NSDecimalNumber decimalNumberWithString:@"51000.00"],
    @"BMW M3 Coupe" : [NSDecimalNumber decimalNumberWithString:@"62000.00"],
    @"BMW X6" : [NSDecimalNumber decimalNumberWithString:@"55015.00"]
};
NSArray *sortedKeys = [prices keysSortedByValueUsingComparator:
                       ^NSComparisonResult(id obj1, id obj2) {
                           return [obj2 compare:obj1];
                       }];
NSLog(@"%@", sortedKeys);

需要注意的是字典的值被作为参数穿入口块而非key本身,其实你也可以对allkeys河allValues进行排序来达到目的。

过滤字典键

同样的,你不能直接过滤一个字典,但是keysOfEntriesPassingTest:方法来进行过滤,如下:

NSDictionary *prices = @{
    @"Mercedes-Benz SLK250" : [NSDecimalNumber decimalNumberWithString:@"42900.00"],
    @"Mercedes-Benz E350" : [NSDecimalNumber decimalNumberWithString:@"51000.00"],
    @"BMW M3 Coupe" : [NSDecimalNumber decimalNumberWithString:@"62000.00"],
    @"BMW X6" : [NSDecimalNumber decimalNumberWithString:@"55015.00"]
};
NSDecimalNumber *maximumPrice = [NSDecimalNumber decimalNumberWithString:@"50000.00"];
NSSet *under50k = [prices keysOfEntriesPassingTest:
                   ^BOOL(id key, id obj, BOOL *stop) {
                       if ([obj compare:maximumPrice] == NSOrderedAscending) {
                           return YES;
                       } else {
                           return NO;
                       }
                   }];
NSLog(@"%@", under50k);

NSMutableDictionary

可变字段可以动态的增删键值对。可变字典的增删和可变sets的增删效率差不多,需要注意的是如果需要对数据频繁增删则这两种数据结构在效率上优先于arrays。

创建可变字典

可变字典可以同样可以使用不可变字典中的工厂方法创建,但是很多这些方法并不直观,所以你可以使用dictionaryWithDictionary:方法进行一个直观的转换:

NSMutableDictionary *jobs = [NSMutableDictionary
                             dictionaryWithDictionary:@{
                                 @"Audi TT" : @"John",
                                 @"Audi Quattro (Black)" : @"Mary",
                                 @"Audi Quattro (Silver)" : @"Bill",
                                 @"Audi A7" : @"Bill"
                             }];
NSLog(@"%@", jobs);

增加和删除键值对

setObject:forKey: 和 removeObjectForKey:方法可以增加修改和删除键值对。当然你甚至可以只要使用下标的方式直接修改(增加或者修改)键值对。

NSMutableDictionary *jobs = [NSMutableDictionary
                             dictionaryWithDictionary:@{
                                 @"Audi TT" : @"John",
                                 @"Audi Quattro (Black)" : @"Mary",
                                 @"Audi Quattro (Silver)" : @"Bill",
                                 @"Audi A7" : @"Bill"
                             }];
// Transfer an existing job to Mary
[jobs setObject:@"Mary" forKey:@"Audi TT"];
// Finish a job
[jobs removeObjectForKey:@"Audi A7"];
// Add a new job
jobs[@"Audi R8 GT"] = @"Jack";

合并字典

可变字典可以使用addEntriesFromDictionary:方法来加载另外一个字典进行扩展。例如:

NSMutableDictionary *jobs = [NSMutableDictionary
                             dictionaryWithDictionary:@{
                                 @"Audi TT" : @"John",
                                 @"Audi Quattro (Black)" : @"Mary",
                                 @"Audi Quattro (Silver)" : @"Bill",
                                 @"Audi A7" : @"Bill"
                             }];
NSDictionary *bakerStreetJobs = @{
    @"BMW 640i" : @"Dick",
    @"BMW X5" : @"Brad"
};
[jobs addEntriesFromDictionary:bakerStreetJobs];

这个方法也可以作为创建可变字典的一个方式:

// Create an empty mutable dictionary
NSMutableDictionary *jobs = [NSMutableDictionary dictionary];
// Populate it with initial key-value pairs
[jobs addEntriesFromDictionary:@{
    @"Audi TT" : @"John",
    @"Audi Quattro (Black)" : @"Mary",
    @"Audi Quattro (Silver)" : @"Bill",
    @"Audi A7" : @"Bill"
}];

注意事项

字典在被迭代的时候不能修改。

使用allKeys or allValues或者键值的嘴阀并不直观,尽可能使用dictionaryWithDictionary: 类方法去创建一个克隆一个字典去处理。

12-7 NSDictionary的更多相关文章

  1. NSDictionary所有API的学习。

    <欢迎大家增加iOS开发学习交流群:QQ529560119> @property (readonly)NSUInteger count; //1.利用指定的key寻找相应的value - ...

  2. Xcode 7.0 SDK(Software Development Kit) 及 Sandbox(沙盒) 存放路径

    1. Sandbox(沙盒) 存放路径 我的硬盘/Users/wj121/Library/Developer/CoreSimulator/Devices/879D7E35-BE50-4620-97E1 ...

  3. python 各模块

    01 关于本书 02 代码约定 03 关于例子 04 如何联系我们 1 核心模块 11 介绍 111 内建函数和异常 112 操作系统接口模块 113 类型支持模块 114 正则表达式 115 语言支 ...

  4. Python Standard Library

    Python Standard Library "We'd like to pretend that 'Fredrik' is a role, but even hundreds of vo ...

  5. 在mybatis中写sql语句的一些体会

    本文会使用一个案例,就mybatis的一些基础语法进行讲解.案例中使用到的数据库表和对象如下: article表:这个表存放的是文章的基础信息 -- ------------------------- ...

  6. Fouandation(NSString ,NSArray,NSDictionary,NSSet) 中常见的理解错误区

    Fouandation 中常见的理解错误区 1.NSString //快速创建(实例和类方法) 存放的地址是 常量区 NSString * string1 = [NSString alloc]init ...

  7. 一些NSArray,NSDictionary,NSSet相关的算法知识

    iOS编程当中的几个集合类:NSArray,NSDictionary,NSSet以及对应的Mutable版本,应该所有人都用过.只是简单使用的话,相信没人会用错,但要做到高效(时间复杂度)精确(业务准 ...

  8. OC 解决NSArray、NSDictionary直接打印中文出现乱码的问题

    在iOS开发中,经常需要查看数组中得元素是否是自己想要的,但是苹果并没有对直接打印数组中得中文作处理,直接打印就会出现一堆很讨厌的东西,解决其实很简单,就是需要通过为NSArray添加分类,重写 - ...

  9. iOS - OC NSDictionary 字典

    前言 @interface NSDictionary<__covariant KeyType, __covariant ObjectType> : NSObject <NSCopyi ...

  10. [示例]NSDictionary编程题-字典的排序应用(iOS4班)

    代码: #import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepo ...

随机推荐

  1. python深浅copy-转自EVA的博客

    感谢Eva_J, http://www.cnblogs.com/Eva-J/p/5534037.html,新手上路,转载纯为自己学习. 初学编程的小伙伴都会对于深浅拷贝的用法有些疑问,今天我们就结合p ...

  2. 在@Async注解下RequestContextHolder.getRequestAttributes() 获得null的情况

    我们有的时候会在service层获取request填充一些诸如用户名和IP地址等信息,这个时候如果不想从Controller层传request,可以在service直接使用 HttpServletRe ...

  3. [六省联考2017]分手是祝愿 期望DP

    表示每次看见期望的题就很懵逼... 但是这题感觉还是值得一做,有可借鉴之处 要是下面这段文字格式不一样的话(虽然好像的确不一样,我也不知道为什么,是直接从代码里面复制出来的,因为我一般都是习惯在代码里 ...

  4. React获取组件实例

    1. 直接new Component() 组件本身也是class,可以new,这样的组件实例意义不大 componentInstance = new Component(); 2. ReactDOM. ...

  5. bzoj4552: [Tjoi2016&Heoi2016]排序(二分+线段树)

    又是久违的1A哇... 好喵喵的题!二分a[p],把大于mid的数改为1,小于等于mid的数改为0,变成01串后就可以用线段树进行那一连串排序了,排序后如果p的位置上的数为0,说明答案比mid小,如果 ...

  6. python邮件服务

    文件形式的邮件 [python] view plaincopy #!/usr/bin/env python3 #coding: utf-8 import smtplib from email.mime ...

  7. Linux IO Scheduler

    一直都对linux的io调度算法不理解,这段时间一直都在看这方面的内容,下面是总结和整理的网络上面的内容.生产上如何建议自己压一下.以实际为准. 每个块设备或者块设备的分区,都对应有自身的请求队列(r ...

  8. Leetcode 703. 数据流中的第K大元素

    1.题目要求 设计一个找到数据流中第K大元素的类(class).注意是排序后的第K大元素,不是第K个不同的元素. 你的 KthLargest 类需要一个同时接收整数 k 和整数数组nums 的构造器, ...

  9. web.xml中出现<servlet-name>default</servlet-name>是什么意思?

    转载自:http://blog.csdn.net/hello5orld/article/details/9407905 在web.xml文件中经常看到这样的配置<servlet-name> ...

  10. Mybatis(3) 映射文件-增删改查

    映射文件: 映射文件是根据数据库模型生成的编写sql脚本xml文件, mapper标签中namespace属性值为对应模型实体类的全类名. <?xml version="1.0&quo ...