Ios 目标C:选择性地组合两个阵列

Ios 目标C:选择性地组合两个阵列,ios,objective-c,nsarray,Ios,Objective C,Nsarray,我知道Objective-C中正常的NSArray连接是如何工作的。这不是问题所在 我有从web服务增量更新的数据。我的对象具有以下类定义(删除了很多): 如果没有更新,那么我只需将两个数组连接在一起即可 但是,如果有更新,我想将这两个数组组合起来,但是只要有一个公共的objectId,则newArray中的项应优先于oldArray中的项 到目前为止,我是这样野蛮地强迫它的: - (void)updateNoteTemplatesWithArray:(NSArray *)newTemplate

我知道Objective-C中正常的
NSArray
连接是如何工作的。这不是问题所在

我有从web服务增量更新的数据。我的对象具有以下类定义(删除了很多):

如果没有更新,那么我只需将两个数组连接在一起即可

但是,如果有更新,我想将这两个数组组合起来,但是只要有一个公共的
objectId
,则
newArray
中的项应优先于
oldArray
中的项

到目前为止,我是这样野蛮地强迫它的:

- (void)updateNoteTemplatesWithArray:(NSArray *)newTemplates {
    NSArray *oldTemplates = [self getNoteTemplates];
    NSMutableArray *combined = [NSMutableArray arrayWithArray:newTemplates];
    for (NoteTemplate *noteTemplate in oldTemplates) {
        NSArray *matches = [combined filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id blockTemplate, NSDictionary<NSString *,id> *bindings) {
            return [((NoteTemplate *)blockTemplate).objectId isEqualToString:noteTemplate.objectId];
        }]];
        if (matches.count == 0) {
            [combined addObject:noteTemplate];
        }
    }
    [self setNoteTemplates:[combined copy]];
}
-(void)updateNodeTemplatesWithArray:(NSArray*)新模板{
NSArray*oldTemplates=[self-getNoteTemplates];
NSMutableArray*组合=[NSMutableArray arrayWithArray:newTemplates];
用于(旧模板中的NoteTemplate*NoteTemplate){
NSArray*matches=[combined filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id块模板,NSDictionary*绑定){
return[((NoteTemplate*)blockTemplate.objectId IsequalString:NoteTemplate.objectId];
}]];
if(matches.count==0){
[合并的addObject:noteTemplate];
}
}
[self-setNoteTemplates:[合并副本]];
}

有没有更优化的方法?我看不出这会影响性能,所以可能没有必要进行优化。尽管如此,这种方法还是让人感觉很粗糙,而且设计得太过火了。

我不知道我是否认为这是一种优雅的方法,但它是一种不那么野蛮的方法。不要在每次通过循环时过滤
组合的
,而是提前获取所有新ID并检查循环中的ID列表

    NSMutableArray <NoteTemplate *> *combined = [NSMutableArray arrayWithArray:newTemplates];
    NSArray <NSString *> *newTemplateIds = [newTemplates valueForKey:@"objectId"];

    for (NoteTemplate *oldTemplate in oldTemplates) {
        if (![newTemplateIds containsObject:oldTemplate.objectId]) {
            [combined addObject:oldTemplate];
        }
    }
NSMutableArray*combined=[NSMutableArray-arrayWithArray:newTemplates];
NSArray*newTemplateId=[newTemplates valueForKey:@“objectId]”;
用于(NoteTemplate*oldTemplate中的oldTemplate){
如果(![newTemplateId包含对象:oldTemplate.objectId]){
[合并的addObject:oldTemplate];
}
}

我不知道我是否会称之为优雅,但这是一种不那么野蛮的方法。不要在每次通过循环时过滤
组合的
,而是提前获取所有新ID并检查循环中的ID列表

    NSMutableArray <NoteTemplate *> *combined = [NSMutableArray arrayWithArray:newTemplates];
    NSArray <NSString *> *newTemplateIds = [newTemplates valueForKey:@"objectId"];

    for (NoteTemplate *oldTemplate in oldTemplates) {
        if (![newTemplateIds containsObject:oldTemplate.objectId]) {
            [combined addObject:oldTemplate];
        }
    }
NSMutableArray*combined=[NSMutableArray-arrayWithArray:newTemplates];
NSArray*newTemplateId=[newTemplates valueForKey:@“objectId]”;
用于(NoteTemplate*oldTemplate中的oldTemplate){
如果(![newTemplateId包含对象:oldTemplate.objectId]){
[合并的addObject:oldTemplate];
}
}

要扩展@Larme的建议并设置用法,您可以尝试以下方法:

@interface NoteTemplate: NSObject

@property (copy, nonatomic) NSString *objectId;
@property (copy, nonatomic) NSString *text;

- (instancetype)initWithObjectId:(NSString *)objectId text:(NSString *)text;

@end

@implementation NoteTemplate
- (instancetype)initWithObjectId:(NSString *)objectId text:(NSString *)text {
    self = [super init];
    if (self != nil) {
        _objectId = objectId;
        _text = text;
    }
    return self;
}

- (BOOL)isEqual:(id)object {
    return [self.objectId isEqualToString:[object objectId]];
}

@end
以及使用代码:

NoteTemplate *nt1 = [[NoteTemplate alloc] initWithObjectId:@"1" text:@"old set"];
NoteTemplate *nt2 = [[NoteTemplate alloc] initWithObjectId:@"2" text:@"old set"];
NoteTemplate *nt3 = [[NoteTemplate alloc] initWithObjectId:@"1" text:@"new set"];
NoteTemplate *nt4 = [[NoteTemplate alloc] initWithObjectId:@"3" text:@"new set"];

NSSet <NoteTemplate *> *oldSet = [NSSet setWithObjects:nt1, nt2, nil];
NSSet <NoteTemplate *> *newSet = [NSSet setWithObjects:nt3, nt4, nil];

NSMutableSet <NoteTemplate *> *mergedSet = [newSet mutableCopy];
[mergedSet unionSet:oldSet];

for (NoteTemplate *note in mergedSet) {
    NSLog(@"Set item %@ %@", note.objectId, note.text);
}

我想这正是你想要的。

要扩展@Larme的建议并使用Set用法,你可以尝试以下方法:

@interface NoteTemplate: NSObject

@property (copy, nonatomic) NSString *objectId;
@property (copy, nonatomic) NSString *text;

- (instancetype)initWithObjectId:(NSString *)objectId text:(NSString *)text;

@end

@implementation NoteTemplate
- (instancetype)initWithObjectId:(NSString *)objectId text:(NSString *)text {
    self = [super init];
    if (self != nil) {
        _objectId = objectId;
        _text = text;
    }
    return self;
}

- (BOOL)isEqual:(id)object {
    return [self.objectId isEqualToString:[object objectId]];
}

@end
以及使用代码:

NoteTemplate *nt1 = [[NoteTemplate alloc] initWithObjectId:@"1" text:@"old set"];
NoteTemplate *nt2 = [[NoteTemplate alloc] initWithObjectId:@"2" text:@"old set"];
NoteTemplate *nt3 = [[NoteTemplate alloc] initWithObjectId:@"1" text:@"new set"];
NoteTemplate *nt4 = [[NoteTemplate alloc] initWithObjectId:@"3" text:@"new set"];

NSSet <NoteTemplate *> *oldSet = [NSSet setWithObjects:nt1, nt2, nil];
NSSet <NoteTemplate *> *newSet = [NSSet setWithObjects:nt3, nt4, nil];

NSMutableSet <NoteTemplate *> *mergedSet = [newSet mutableCopy];
[mergedSet unionSet:oldSet];

for (NoteTemplate *note in mergedSet) {
    NSLog(@"Set item %@ %@", note.objectId, note.text);
}

我想这就是你想要的。

你真的在乎秩序而不是口是心非吗?使用带有key
objectId
的字典,然后根据需要对它们进行排序,怎么样?也许是
NSMutableOrderedSet
(请参阅)您真的关心顺序而不是重复性吗?使用带有key
objectId
的字典,然后根据需要对它们进行排序,怎么样?可能是一个
NSMutableOrderedSet
(请参阅)这是一个不错的方法。我认为顺序在我的回答中很重要,但可能不是。@TomHarrington在案例中顺序很重要
n可能会按照您的建议使用derset
。然后应该从
oldSet
创建
mergedSet
,而
unionSet
函数应该替换为
[[mergedSet-minus:newSet]union:newSet]
哦,对了。我一直在做Swift,以至于忘了查找
NSMutableOrderedSet
。取而代之的是,我看的是
ensorderedset
,没有考虑寻找额外的可变性方法。我最终使用了这个方法的一个修改版本,因为顺序对我来说确实很重要,但在我组合数组的那一部分中就不重要了。我还需要能够删除项,因此除了
isEqual:
方法之外,我还添加了
hash
方法。谢谢你把我带到那里!这是一个很好的方法。我认为顺序在我的回答中很重要,但可能不是。@TomHarrington在案例中顺序很重要
n可能会按照您的建议使用derset
。然后应该从
oldSet
创建
mergedSet
,而
unionSet
函数应该替换为
[[mergedSet-minus:newSet]union:newSet]
哦,对了。我一直在做Swift,以至于忘了查找
NSMutableOrderedSet
。取而代之的是,我看的是
ensorderedset
,没有考虑寻找额外的可变性方法。我最终使用了这个方法的一个修改版本,因为顺序对我来说确实很重要,但在我组合数组的那一部分中就不重要了。我还需要能够删除项,因此除了
isEqual:
方法之外,我还添加了
hash
方法。谢谢你把我带到那里!