簡體   English   中英

從NSDrray的NSArray的NSArray中提取特性

[英]extracting properties from NSArray of NSArray of NSDictionary

此問題類似於從NSArray對象中提取屬性 ,但用於深度提取。

為簡單起見,我在下面的示例中引用的對象是NSStrings。

我有兩個案例我想解決。

帶有對象的NSArray NSArray的NSArray

最好使用鍵值編碼,從以下結構中,我想將所有“標題”提取到單個可枚舉列表中:

NSArray *list1 = @[
    @[
        @{@"title":@"A", @"description":...},
        @{@"title":@"B", @"description":...},
    ],
    @[
        @{@"title":@"C", @"description":...},
        @{@"title":@"D", @"description":...},
    ],
];

期望的結果將是例如:

@[@"A", @"B", @"C", @"D"]

帶有NSArray對象的NSDictionary的NSArray

最好使用鍵值編碼,從以下結構中,我想將“標題”列表提取到一個可枚舉列表中:

NSArray *list2 = @[
    @{
        @"titles":@[
            @"A",
            @"B",
        ],
        @"descriptions":...,
    },
    @{
        @"titles":@[
            @"C",
            @"D",
        ],
        @"descriptions":...,
    },
];

期望的結果將是例如:

@[@"A", @"B", @"C", @"D"]

筆記

  • 我的真實情況涉及NSOrderedSetNSOrderedSet對象的第一個列表和NSOrderedSetNSDictionaryNSOrderedSet對象的第二個列表,但這不應該影響我認為的答案。

  • 我寫道,我更喜歡使用鍵值編碼,但這不是必須的。 我只是想避免,如果可能的話,寫for (... in ...)enumateObjectWithBlock: .

  • 同樣,這應該不重要,但對象是來自獲取請求的NSManagedObject。 所以我知道我可以直接優化獲取請求,但我仍然想知道是否有很好的選擇。

在這種情況下,KVC確實可以通過名為@unionOfArraysCollection運算符進行 @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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM