ios - Objective-C:有选择地组合两个数组

标签 ios objective-c nsarray

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

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

//  NoteTemplate.h
#import <UIKit/UIKit.h>
@interface NoteTemplate 

@property (copy, nonatomic) NSString *objectId;

我正在设备上缓存这些列表,并在启动时检查我的数据库中是否有任何新的或更新的 NoteTemplate 对象要加载。所以,我最终得到了两个数组:

NSArray <NoteTemplate *> *oldArray
NSArray <NoteTemplate *> *newArray

如果没有更新,那么我需要做的就是简单地将两个数组连接在一起,仅此而已。

如果有更新,但是,我想合并两个数组,但是只要有一个共同的objectIdnewArray中的项目> 应优先于 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]];
}

有没有更优化的方法来做到这一点?我看不出这会影响性能,所以也许不需要优化。不过,这种方法感觉很老套,而且设计过度。

最佳答案

要使用 Set 扩展@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);
}

执行此代码后,您将在日志中看到:

Set item 3 new set
Set item 1 new set
Set item 2 old set

我想这就是您要找的。

关于ios - Objective-C:有选择地组合两个数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48771147/

相关文章:

ios - 将 TLS V1.1/V 1.2 与 NSURLConnection 结合使用

ios - 在 imageview 中加载来自互联网的图像的函数

objective-c - 强制 UISearchController 全屏显示搜索结果表

ios - 需要使用 CallKit 在 iOS 10 中调用详细信息

ios - 如何在 Cordova 中从 CDVPlugin 显示 ViewController?

ios - 将 NSArray 元素分配给适当对象的最佳方法是什么?

objective-c - 在 UITableView 中使用插入行

objective-c - NSDictionary objectAtIndex 上的 SIGABRT : unrecognized selector

ios - 错误 : *use of undeclared identifier 'firstObject' on a NSArray on an iOS 7 project

iphone - 使用 NSPredicate 过滤带有字典的数组