1

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.

2
  • Can you clarify: do you want to include rooms where a) any occupant matches either 2285222 or 2285224, or b) both 2285222 and 2285224 were occupants? And do you want to include rooms which also have other occupantIDs in addition to these two? Commented Feb 6, 2015 at 17:16
  • occupantsIDs are known so it is these only and i want to filter according to that. If we can get result from using either one then also it is fine for my case but i suggest better to use both for comparing. Commented Feb 6, 2015 at 17:18

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your effort. Your solution is working for me but can you tell me in brief how this is going to compare ?
I'll put an explanation in my answer.
Thank a lot for your effort.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.