Using NSPredicate in 2D Arrays

人走茶凉 提交于 2019-12-09 13:51:26

问题


This question is based off of the same app/source from my previous question which can be found here:

How to manage memory using classes in Objective-C?

I have a nested array which looks something like this when printed out (I only copied and pasted a brief part of it).

(
        (
        <Term: 0x4256420>,
        <Term: 0x420fa40>,
        <Term: 0x4257bd0>,
        <Term: 0x4257cf0>,
        <Term: 0x4257d90>,
        <Term: 0x4257e30>
    ),
        (
        <Term: 0x4257e50>,
        <Term: 0x4257f90>,
        <Term: 0x4257fb0>,
        <Term: 0x42580e0>,
        <Term: 0x4258170>,
        <Term: 0x4258210>,
        <Term: 0x4258230>,
        <Term: 0x4258360>,
        <Term: 0x4258400>,
        <Term: 0x42584a0>,
        <Term: 0x4258540>,
        <Term: 0x42585e0>,
        <Term: 0x4258670>,
        <Term: 0x4258710>
    ),

And here is my code for the search part of my table:

- (NSInteger)tableView:(UITableView *)aTableView numberOfRowsInSection:(NSInteger)section 
{
    // Normal table
    if (aTableView == self.tableView) return [[self.sectionArray objectAtIndex:section] count];

    // Search table
    //NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name contains[cd] %@", self.searchBar.text];
    //self.filteredArray = [self.crayonColors filteredArrayUsingPredicate:predicate];
 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name contains[cd] %@", self.searchBar.text];
    self.filteredArray = [[self.sectionArray objectAtIndex:section] filteredArrayUsingPredicate:predicate];


    return self.filteredArray.count;
}

I am getting the error that I cannot allocate enough room which means that I must be doing something wrong, I just cannot figure out what.

The commented out portion of the search part in the above method works but crayonColors is just a simple NSMutableDictionary of NSStrings and does not have arrays nested inside of it.

Thanks in advance!


回答1:


As far as I'm aware, you can't do this with a single predicate. However, you can do it with a key-path operator and a predicate in two separate calls.

So, you have an array of arrays of terms. You want a single array of terms where its name contains 'A' (for example). Here's what you do:

NSArray * allTerms = ...; //your array of arrays of terms
NSArray * collapsedTerms = [allTerms valueForKeyPath:@"@unionOfArrays.self"];

NSPredicate * filter = [NSPredicate predicateWithFormat:@"name CONTAINS[cd] %@", @"A"];
NSArray * filteredTerms = [collapsedTerms filteredArrayUsingPredicate:filter];

The magic here is the valueForKeyPath: bit. The @unionOfArrays operator takes an array of arrays of objects, and returns an array of objects. Here's what it's doing: The NSArray is going to break the keypath up by ., giving it @unionOfArrays and self. It's going to recurse and invoke valueForKeyPath: on itself using the second bit (self), and it's going to get back an array of arrays. It's then going to mash all those arrays together into a single array, ignoring duplicates. (If you want to remove duplicates, use @distinctUnionOfArrays instead)

Once we have that array of objects, we can then filter it normally using a simple name CONTAINS 'blah' predicate.

(I thought I might be able to get this to work using a SUBQUERY, but that's a strange beast and nothing was immediately obvious to me.)

For the super intrepid, you could do this with a single method call using KickingBear's collection extensions (available here), but I would strongly advise against using hacks like that in a production setting. :)



来源:https://stackoverflow.com/questions/4559427/using-nspredicate-in-2d-arrays

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!