[英]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.