Quick Explanation of SUBQUERY in NSPredicate Expression

前端 未结 3 1582
予麋鹿
予麋鹿 2020-11-27 18:03

There appears to be zero documentation about the SUBQUERY keyword from Apple and I can\'t find a simple explanation about it on SO or on Google. It\'s a conspiracy! ;)

相关标签:
3条回答
  • 2020-11-27 18:28

    This is what a subquery evaluates to. (Found from this mailing list thread, the #1 hit for “NSPredicate subquery” in Google.) That bit of documentation also explains how the predicate format string syntax relates to it.

    0 讨论(0)
  • 2020-11-27 18:34

    Subquery represents a predicate (third argument - $x IN %@) that is evaluated on all objects (second argument - $x - it's like a variable name in foreach) of a relationship (first argument - Bs). Similarly to regular query returns a list of objects.

    I see in many places that people use $x almost dogmatically, but $object in objects relationship makes perfect sense as well (or $city in cities...) :)

    I've written a blog post about SUBQUERY some time ago. You can check it here.

    0 讨论(0)
  • 2020-11-27 18:41

    And for people who don't quite get what the documentation is saying, a SUBQUERY is essentially this:

    SUBQUERY(collection, variableName, predicateFormat)
    

    And could (simplistically) be implemented like this:

    id resultingCollection = ...; //a new collection, either a mutable set or array
    NSMutableDictionary * substitutions = [NSMutableDictionary dictionary];
    NSPredicate * p = [NSPredicate predicateWithFormat:predicateFormat];
    for (id variable in collection) {
      [substitutions setObject:variable forKey:variableName];
      NSPredicate * filter = [p predicateWithSubstitutionVariables:substitutions];
      if ([filter evaluateWithObject:collection] == YES) {
        [resultingCollection addObject:variable];
      }
    }
    return resultingCollection;
    

    So in a nutshell, a SUBQUERY is basically taking a collection of objects and filtering out various objects based on the predicate expression of the SUBQUERY, and returning the resulting collection. (And the predicate itself can contain other SUBQUERYs)

    Example:

    NSArray * arrayOfArrays = [NSArray arrayWithObjects:
                               [NSArray arrayWithObjects:....],
                               [NSArray arrayWithObjects:....],
                               [NSArray arrayWithObjects:....],
                               [NSArray arrayWithObjects:....],
                               [NSArray arrayWithObjects:....],
                               [NSArray arrayWithObjects:....],
                               nil];
    NSPredicate * filter = [NSPredicate predicateWithFormat:@"SUBQUERY(SELF, $a, $a.@count > 42)"];
    NSArray * filtered = [arrayOfArrays filteredArrayUsingPredicate:filter];
    //"filtered" is an array of arrays
    //the only arrays in "filtered" will have at least 42 elements each
    
    0 讨论(0)
提交回复
热议问题