[英]extracting properties from NSArray of NSArray of NSDictionary
此问题类似于从NSArray对象中提取属性 ,但用于深度提取。
为简单起见,我在下面的示例中引用的对象是NSStrings。
我有两个案例我想解决。
最好使用键值编码,从以下结构中,我想将所有“标题”提取到单个可枚举列表中:
NSArray *list1 = @[
@[
@{@"title":@"A", @"description":...},
@{@"title":@"B", @"description":...},
],
@[
@{@"title":@"C", @"description":...},
@{@"title":@"D", @"description":...},
],
];
期望的结果将是例如:
@[@"A", @"B", @"C", @"D"]
最好使用键值编码,从以下结构中,我想将“标题”列表提取到一个可枚举列表中:
NSArray *list2 = @[
@{
@"titles":@[
@"A",
@"B",
],
@"descriptions":...,
},
@{
@"titles":@[
@"C",
@"D",
],
@"descriptions":...,
},
];
期望的结果将是例如:
@[@"A", @"B", @"C", @"D"]
我的真实情况涉及NSOrderedSet
的NSOrderedSet
对象的第一个列表和NSOrderedSet
的NSDictionary
与NSOrderedSet
对象的第二个列表,但这不应该影响我认为的答案。
我写道,我更喜欢使用键值编码,但这不是必须的。 我只是想避免,如果可能的话,写for (... in ...)
或enumateObjectWithBlock:
.
同样,这应该不重要,但对象是来自获取请求的NSManagedObject。 所以我知道我可以直接优化获取请求,但我仍然想知道是否有很好的选择。
在这种情况下,KVC确实可以通过名为@unionOfArrays
的Collection运算符进行 @unionOfArrays
。 此运算符的一个作用是展平数组,因此您的第一个示例非常简单。
[list1 valueForKeyPath:@"@unionOfArrays.title"]
第二个非常相似,但你必须按相反的顺序进行。 首先提取所有titles
数组,然后展平它们。
[list2 valueForKeyPath:@"titles.@unionOfArrays.self"]
self
是必要的 - 虽然看似多余 - 因为,根据上面链接的文档
除
@count
,所有集合运算符都需要集合运算符右侧的键路径。
对于NSOrderedSet
,似乎您可以在键路径中使用其array
属性来转换内部集合,然后再对它们进行操作,但由于某种原因,这会产生错误。 我找到了这个有趣的小贴士,然而, 由Nicolas Bouilleaud发布在GitHub上 :
// Convert each OrderedSet to an Array to mute the error.
NSLog(@"union : %@",[data valueForKeyPath:@"@distinctUnionOfArrays.values.@array"]);
这个奇怪的@array
运算符适用于您的NSOrderedSet
示例输入:
NSOrderedSet *list1 = [NSOrderedSet orderedSetWithObjects:[NSOrderedSet orderedSetWithArray:@[ @{@"title":@"A"}, @{@"title":@"B"} ]], [NSOrderedSet orderedSetWithArray:@[ @{@"title":@"C"}, @{@"title":@"D"} ]], nil];
// Note also converting outer set to array first
NSLog(@"%@", [list1.array valueForKeyPath:@"@unionOfArrays.title.@array"]);
NSOrderedSet *list2 = [NSOrderedSet orderedSetWithArray:@[ @{ @"titles":[NSOrderedSet orderedSetWithObjects: @"A", @"B", nil] }, @{ @"titles":[NSOrderedSet orderedSetWithObjects: @"C", @"D", nil] } ]];
// Note also converting outer set to array first
NSLog(@"%@", [list2.array valueForKeyPath:@"titles.@unionOfArrays.self.@array"]);
但我不知道为什么 。 我无法弄清楚它来自何处或它正在做什么(特别是为什么它最后)。
感谢Josh关于NSArray的答案。 当我问我的问题时,我使用NSArray描述它,因为用现代的@[]
语法编写它更容易。 我无法想象,为NSArray的最合适的答案会是我的真实情况不符 NSOrderedSet
。
所以,我的真实案例更接近于此:
NSOrderedSet *list1 = [NSOrderedSet orderedSetWithObjects:[NSOrderedSet orderedSetWithArray:@[ @{@"title":@"A"}, @{@"title":@"B"} ]], [NSOrderedSet orderedSetWithArray:@[ @{@"title":@"C"}, @{@"title":@"D"} ]], nil];
NSOrderedSet *list2 = [NSOrderedSet orderedSetWithArray:@[ @{ @"titles":[NSOrderedSet orderedSetWithObjects: @"A", @"B", nil] }, @{ @"titles":[NSOrderedSet orderedSetWithObjects: @"C", @"D", nil] } ]];
我能找到的NSOrderedSet的唯一解决方案是遗憾地使用循环:
NSMutableOrderedSet *listA = [NSMutableOrderedSet orderedSet];
for (NSOrderedSet *set in [list1 valueForKey:@"title"]) {
[listA unionOrderedSet:set];
}
NSMutableOrderedSet *listB = [NSMutableOrderedSet orderedSet];
for (NSDictionary *object in list2) {
[listB unionOrderedSet:object[@"titles"]];
}
[编辑:显然Josh找到了一个无证的@array
运算符来解决这个问题。 Contratz!]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.