12-7 NSDictionary
原文: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:
类方法去创建一个克隆一个字典去处理。
最新文章
- 一些有用的configue参数
- windows2008r2的时间同步小结
- 为什么要用hibernate 与基于数据库表结构的项目开发
- 解决ScrollView嵌到listView冲突问题
- Eclipse PHP Studio(EPP)
- Apache与Nginx虚拟主机设置(多域名和多端口的区别)
- Oracle 权限查询
- unity3d设置3D模型显示在2D背景之前(多个相机分层显示)(转)
- 基于HtmlUnit的模板的网页数据抽取
- TcxVerticalGrid 汇总
- spring 学习的开源项目
- DropDownList四级联动
- 所有城市list每次从页面花1段时间抽取后写入到数组,
- php通过token验证表单重复提交
- Angular - - $cacheFactory
- nginx rewrite (转发)
- 11-Python操作excel
- 不要使用Integer做HashMap的key,尤其在json序列化的时候
- day014 模块
- solr 5.5使用 和pyg里 的4.10.3版 部署到tomcat中不一样(不使用内置jetty)
热门文章
- [洛谷P2057][SHOI2007]善意的投票
- Java.util包简单总结
- bzoj Usaco补完计划(优先级 Gold>;Silver>;资格赛)
- 四连测Day3
- 洛谷P4135 作诗 (分块)
- Codeforces Round #540 (Div. 3) 部分题解
- G. Trace ACM-ICPC 2018 徐州赛区网络预赛 线段树写法
- arp协议及简单应用
- getQueryString----获取url中得参数
- eclipse常见问题解决方案