从 NSDictionary 的 NSArray 的 NSArray 中提取属性
extracting properties from NSArray of NSArray of NSDictionary
此题与extracting properties from NSArray of objects相似,但提取更深
为了简单起见,我在下面的示例中指的 objects 是 NSStrings.
我有两个案例想解决
带有对象的 NSDictionary 的 NSArray 的 NSArray
最好使用键值编码,从以下结构中,我想将所有 "title" 提取到一个可枚举列表中:
NSArray *list1 = @[
@[
@{@"title":@"A", @"description":...},
@{@"title":@"B", @"description":...},
],
@[
@{@"title":@"C", @"description":...},
@{@"title":@"D", @"description":...},
],
];
期望的结果例如是:
@[@"A", @"B", @"C", @"D"]
NSDictionary 的 NSArray 和对象的 NSArray
最好使用键值编码,从以下结构中,我想将 "titles" 的列表提取到单个可枚举列表中:
NSArray *list2 = @[
@{
@"titles":@[
@"A",
@"B",
],
@"descriptions":...,
},
@{
@"titles":@[
@"C",
@"D",
],
@"descriptions":...,
},
];
期望的结果例如是:
@[@"A", @"B", @"C", @"D"]
备注
我的真实案例涉及第一个列表的 NSOrderedSet
个对象和 NSDictionary
个对象的 NSOrderedSet
个 NSOrderedSet
个对象对于第二个列表,但这不应该影响我认为的答案。
我写过我更愿意使用键值编码,但这不是必须的。我只是想尽可能避免写 for (... in ...)
或 enumateObjectWithBlock:
.
同样,这应该无关紧要,但对象是来自获取请求的 NSManagedObject。所以我知道我可以直接优化获取请求,但我仍然想知道是否有更好的选择。
在这种情况下,KVC 确实可以通过 Collection Operator called @unionOfArrays
执行您的命令。此运算符的一个作用是展平数组,因此您的第一个示例非常简单。
[list1 valueForKeyPath:@"@unionOfArrays.title"]
第二个很相似,但是你必须按照相反的顺序来做。首先提取所有 titles
数组,然后将它们展平。
[list2 valueForKeyPath:@"titles.@unionOfArrays.self"]
self
是必要的——尽管它看起来多余——因为根据上面链接的文档
All the collection operators, with the exception of @count
, require a key path to the right of the collection operator.
对于NSOrderedSet
,似乎你可以在关键路径中使用它的array
属性来转换内部集合,然后再对它们进行操作,但由于某种原因,这会产生错误。然而,我发现了这个有趣的花絮,已发布 on GitHub by Nicolas Bouilleaud:
// Convert each OrderedSet to an Array to mute the error.
NSLog(@"union : %@",[data valueForKeyPath:@"@distinctUnionOfArrays.values.@array"]);
这个奇怪的 @array
operator 适用于您的 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 最合适的答案是 incompatible 与我的真实案例 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
操作员来解决这个问题。反对!]
此题与extracting properties from NSArray of objects相似,但提取更深
为了简单起见,我在下面的示例中指的 objects 是 NSStrings.
我有两个案例想解决
带有对象的 NSDictionary 的 NSArray 的 NSArray
最好使用键值编码,从以下结构中,我想将所有 "title" 提取到一个可枚举列表中:
NSArray *list1 = @[
@[
@{@"title":@"A", @"description":...},
@{@"title":@"B", @"description":...},
],
@[
@{@"title":@"C", @"description":...},
@{@"title":@"D", @"description":...},
],
];
期望的结果例如是:
@[@"A", @"B", @"C", @"D"]
NSDictionary 的 NSArray 和对象的 NSArray
最好使用键值编码,从以下结构中,我想将 "titles" 的列表提取到单个可枚举列表中:
NSArray *list2 = @[
@{
@"titles":@[
@"A",
@"B",
],
@"descriptions":...,
},
@{
@"titles":@[
@"C",
@"D",
],
@"descriptions":...,
},
];
期望的结果例如是:
@[@"A", @"B", @"C", @"D"]
备注
我的真实案例涉及第一个列表的
NSOrderedSet
个对象和NSDictionary
个对象的NSOrderedSet
个NSOrderedSet
个对象对于第二个列表,但这不应该影响我认为的答案。我写过我更愿意使用键值编码,但这不是必须的。我只是想尽可能避免写
for (... in ...)
或enumateObjectWithBlock:
.同样,这应该无关紧要,但对象是来自获取请求的 NSManagedObject。所以我知道我可以直接优化获取请求,但我仍然想知道是否有更好的选择。
在这种情况下,KVC 确实可以通过 Collection Operator called @unionOfArrays
执行您的命令。此运算符的一个作用是展平数组,因此您的第一个示例非常简单。
[list1 valueForKeyPath:@"@unionOfArrays.title"]
第二个很相似,但是你必须按照相反的顺序来做。首先提取所有 titles
数组,然后将它们展平。
[list2 valueForKeyPath:@"titles.@unionOfArrays.self"]
self
是必要的——尽管它看起来多余——因为根据上面链接的文档
All the collection operators, with the exception of
@count
, require a key path to the right of the collection operator.
对于NSOrderedSet
,似乎你可以在关键路径中使用它的array
属性来转换内部集合,然后再对它们进行操作,但由于某种原因,这会产生错误。然而,我发现了这个有趣的花絮,已发布 on GitHub by Nicolas Bouilleaud:
// Convert each OrderedSet to an Array to mute the error.
NSLog(@"union : %@",[data valueForKeyPath:@"@distinctUnionOfArrays.values.@array"]);
这个奇怪的 @array
operator 适用于您的 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 最合适的答案是 incompatible 与我的真实案例 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
操作员来解决这个问题。反对!]