Search code examples
objective-cnsarraypredicate

Objective-C: Reduce properties in NSArray


I have two arrays of similar but different objects that I would like to combine. The objects have some properties in common and some unique to one that I don't especially need. So my thought is to simplify them down to the properties they have in common.

My problem is I have not found a way to strip out properties of objects in an array. I would imagine it might be possible with a predicate or key value, however, I have not found a way. The properties are heterogeneous, ie strings, NSDates and Bools. There are multiple objects in the array with values for those properties.

Example:

NSArray1

id (NSNuber)|title (NSString)|color(NSString)

NSArray2
id (NSNumber)|title (NSString)|length(NSNumber)

How would I strip out the color from NSArray1 and length from NSArray2 to get two arrays with id|title


Solution

  • The question is a little ambiguous because it doesn't indicate the type of objects in the arrays, but lets suppose they are dictionaries.

    There's no need to strip out properties, because while building the resulting array, you'll be abandoning both of the source objects (in favor of a mutable copy)...

    NSArray *array1, *array2;  // these are initialized with the dictionaries
    NSMutableArray *result = [NSMutableArray array];
    for (NSDictionary *d1 in array1) {
        NSDictionary *d2 = [self elementMatching:d1 in:array2];
        if (!d2) {
            // what should we do if there's no match?
            // maybe ignore, maybe just add it to result?
        } else {
            // here, d2 has id, title, length.  needs color from d1
            NSMutableDictionary *newD2 = [d2 mutableCopy];
            newD2[@"color"] = d1[@"color"];
            [result addObject:newD2];
        }
    }
    
    - (NSDictionary *)elementMatching:(NSDictionary *)d in:(NSArray *)array {
        for (NSDictionary *element in array) {
            if ([element[@"id"] isEqual:element[@"id"]] && [element[@"title"] isEqual:element[@"title"]]) 
                return element;
        }
        return nil;
    }
    

    Notice that this loop considers the case where there is no object in array2 that matches one found in array1. You should decide what to do there based on your requirements. It also doesn't consider the case of elements of array2 that don't have counterparts in array1. You would need another (similar) loop to handle those.