简体   繁体   中英

Filter array using predicate based on another array that is key for predicate

Hello everyone this may be silly question and may be asked before, I want to filter the array using predicate. I have an array which contains dictionary of same type like following.

<NSArrayM>(
ID:54d3ca82535c12243400c254                      
Room JID:(null)                      
name:(null)                      
photo:(null)                      
type:3                      
lastMessage:Gand                      
lastMessageDate:2015-02-05 20:02:47 +0000                      
occupantIDs:(
2285222,
2285224
)                      
userID:2285224                      
unreadMessagesCount:4                      
lastMessageUserID:2285224
)

I want to filter the array by the key occupantsIDs which is array. I want to create predicate which match occupantIDs as key. I want to know can i use that for filter the array.

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"occupantIDs = @[2285222,2285224]"];        
NSArray *filterArray = [dialogs filteredArrayUsingPredicate:predicate];

Any answer can be appreciated.

If you use:

NSPredicate *filter = [NSPredicate predicateWithFormat:@"SUBQUERY(occupantIDs, $x, $x == %@).@count > 0 AND SUBQUERY(occupantIDs, $x, $x == %@).@count > 0", @2285222,@2285224];

this will match any items where the occupantIDs array includes both 2285222 and 2285224 (and may also include other occupantIDs).

If you want to exclude those items which also have other occupantIDs, use the following:

NSPredicate *filter = [NSPredicate predicateWithFormat:@"SUBQUERY(occupantIDs, $x, $x == %@).@count > 0 AND SUBQUERY(occupantIDs, $x, $x == %@).@count > 0 AND SUBQUERY(occupantIDs, $x, $x != %@ AND $x != %@).@count = 0", @2285222,@2285224,@2285222,@2285224];

To explain how these work: first, each %@ is replaced by the respective item from the list of arguments (@2285222, etc). So the first SUBQUERY becomes "SUBQUERY(occupantIDs, $x, $x == 2285222)". This is equivalent to "filter the array 'occupantIDs' by testing whether each element '$x' is equal to 2285222." (Note that '$x' is an arbitrary name for the element - it could be '$y' or whatever you like.) The ".@count > 0" then checks to see whether this filtered array has any items. Put another way, at least one occupantID matches 2285222.

The second SUBQUERY is basically the same, but for 2285224. So you can interpret the overall predicate as "include those items where the occupantIDs array has any elements that match 2285222 AND any elements that match 2285224".

To exclude items which also have other occupantIDs, I added another clause which uses the same technique to include only those items where the occupantIDs array has NO items which do NOT match 2285222 or 2285224.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM