Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 比较两个字典数组并添加/删除项_Ios_Objective C_Nsarray_Nsdictionary - Fatal编程技术网

Ios 比较两个字典数组并添加/删除项

Ios 比较两个字典数组并添加/删除项,ios,objective-c,nsarray,nsdictionary,Ios,Objective C,Nsarray,Nsdictionary,我有两个这样的字典数组 arrCurrent = [{ id = 1; name = "Name1"; },{ id = 2; name = "Name2"; },{ id = 3; name = "Name3"; }]; arrUpdated = [{ id = 1; name = "Name1 has changed";

我有两个这样的字典数组

  arrCurrent = [{
        id = 1;
        name = "Name1";
    },{
        id = 2;
        name = "Name2";
    },{
        id = 3;
        name = "Name3";
    }];


    arrUpdated = [{
        id = 1;
        name = "Name1 has changed";
    },{
        id = 2;
        name = "Name2 has changed";
    },{
        id = 4;
        name = "Name4 is a new item";
    }];
arrFinal = [{
        id = 1;
        name = "Name1 has changed";
    },{
        id = 2;
        name = "Name2 has changed";
    },{
        id = 3;
        name = "Name3";
    },{
        id = 4;
        name = "Name4 is a new item";
    }];
我的要求是根据以下条件合并这两个数组

1) 如果arrUpdated包含新项目(id为new的项目),则应将其添加为新项目

2) 如果arrUpdated包含与arrCurrent contains的id相同的项目,则应使用更新的项目替换这些项目

最后的数组应该是这样的

  arrCurrent = [{
        id = 1;
        name = "Name1";
    },{
        id = 2;
        name = "Name2";
    },{
        id = 3;
        name = "Name3";
    }];


    arrUpdated = [{
        id = 1;
        name = "Name1 has changed";
    },{
        id = 2;
        name = "Name2 has changed";
    },{
        id = 4;
        name = "Name4 is a new item";
    }];
arrFinal = [{
        id = 1;
        name = "Name1 has changed";
    },{
        id = 2;
        name = "Name2 has changed";
    },{
        id = 3;
        name = "Name3";
    },{
        id = 4;
        name = "Name4 is a new item";
    }];
希望我的要求是明确的,什么是最好的方式做到这一点

这就是我试图做到的。但是这种方法会得到重复的项。此外,通过数组循环并不是最好的方法

请注意:实际代码包含与上述数组名称不同的名称。但逻辑是一样的

arrSavedSectors=arrCurrent

arrAllUpdatedSectors=arrrUpdated

ArrFilteredSector=arrFinal

NSMutableArray *arrSavedSectors = [[NSMutableArray alloc]initWithArray:  [dictionary objectForKey:@"ArrSectors"]];
NSMutableArray *arrFilteredSectors = [[NSMutableArray alloc]initWithArray:arrSavedSectors];

// add updated sectors to list
NSArray *arrAllUpdatedSectors = [NSArray arrayWithArray:[sectorDetails objectForKey:@"AllUpdatedSectors"]];

if([arrSavedSectors count] > 0){
    // check for updated sectors (Which are already saved in the plist, but recently updated some details)
    for(NSDictionary *dicSector in arrSavedSectors){
        for(NSDictionary *dicUpdatedSector in arrAllUpdatedSectors){
            if([[dicUpdatedSector objectForKey:@"id"] isEqualToString:[dicSector objectForKey:@"id"]]){
                [arrFilteredSectors removeObject:dicSector];
                [arrFilteredSectors addObject:dicUpdatedSector];
            }
            else{
                [arrFilteredSectors addObject:dicUpdatedSector];
            }
        }

    }
}
else{
    [arrFilteredSectors addObjectsFromArray:arrAllUpdatedSectors];
}

我认为一个循环可以做到这一点

   for(int x=0;x<[arrUpdate count];x++){
       //condition 2
        if([[arrCurrent valueForKey:@"id"] containsObject:[[arrUpdate objectAtIndex:x] valueForKey:@"id"]]){

       }
     //condition 1
      else{
         [arrCurrent addObject: [arrUpdate objectAtIndex:x]]

       }
    }

一些集合操作的时间

最困难的部分是,我们需要给我们正在使用的集合一个理解对象是相等的和相同的

字典中没有一个是这样的,但是我们可以引入一个包装器类来使用它的实现

@interface Wrapper : NSObject
@property NSDictionary *dictionary;
-(instancetype)initWithDictionary: (NSDictionary *)dict;
@end

@implementation Wrapper

-(instancetype)initWithDictionary: (NSDictionary *)dict
{
    self = [super init];
    if (self) {
        self.dictionary = dict;
    }
    return self;
}

-(BOOL)isEqual:(Wrapper *)object
{
    return [self.dictionary[@"id"] isEqual: object.dictionary[@"id"]];
}

-(NSUInteger)hash
{
    return [self.dictionary[@"id"] unsignedIntegerValue];
}

-(NSString *)description
{
    return [self.dictionary description];
}

@end
现在我们可以用它来包装每一本字典

NSArray *arrCurrent = @[[[Wrapper alloc] initWithDictionary: @{@"id": @(1), @"name" : @"Name 1"}],
                        [[Wrapper alloc] initWithDictionary: @{@"id": @(2), @"name" : @"Name 2"}],
                        [[Wrapper alloc] initWithDictionary: @{@"id": @(3), @"name" : @"Name 3"}]];

NSArray *arrUpdated = @[[[Wrapper alloc] initWithDictionary: @{@"id": @(1), @"name" : @"Name 1 has Changed"}],
                        [[Wrapper alloc] initWithDictionary: @{@"id": @(2), @"name" : @"Name 2 has Changed"}],
                        [[Wrapper alloc] initWithDictionary: @{@"id": @(4), @"name" : @"Name 4"}]];
下一步,我们将从中创建集合

NSSet *setCurrent = [NSSet setWithArray:arrCurrent];
NSSet *setUpdated = [NSSet setWithArray:arrUpdated];
现在我们做集合运算

NSMutableSet *setFinal = [setUpdated mutableCopy];
[setFinal unionSet:setCurrent];
最后,我们使用键值编码来打开字典

NSArray *arrFinal = [setFinal valueForKey:@"dictionary"];
结果:

{(
    {
        id = 1;
        name = "Name 1 has Changed";
    },
        {
        id = 2;
        name = "Name 2 has Changed";
    },
        {
        id = 3;
        name = "Name 3";
    },
        {
        id = 4;
        name = "Name 4";
    }
)}

这段代码的一个问题是:包装器在其他情况下没有用处,因为确定相等性的规则可能不同,因此在需要时能够定义它们会很有用。我们可以使用块来实现这一点:

包装器变为

@interface Wrapper : NSObject
@property id object;
@property (copy) BOOL (^equalComparator)(id a, id b);
@property (copy) NSUInteger (^hashBlock)(id a);
@end

@implementation Wrapper

-(instancetype)initWithObject: (id)obj
              equalComparator:(BOOL (^)(id a, id b))equalComparator
                    hashBlock:(NSUInteger (^)(id a))hashBlock
{
    self = [super init];
    if (self) {
        self.equalComparator = equalComparator;
        self.hashBlock = hashBlock;
        self.object = obj;
    }
    return self;
}

-(BOOL)isEqual:(Wrapper *)object
{
    return self.equalComparator(self.object, object.object);
}

-(NSUInteger)hash
{
    return self.hashBlock(self.object);
}

-(NSString *)description
{
    return [self.object description];
}

@end
我们使用它就像

BOOL (^eq)(NSDictionary *a, NSDictionary *b) = ^(NSDictionary *a, NSDictionary *b){
    return [a[@"id"] isEqual: b[@"id"]];
};

NSUInteger (^hash)(NSDictionary *a) = ^(NSDictionary *a){
    return [a[@"id"] unsignedIntegerValue];
};

NSArray *arrCurrent = @[[[Wrapper alloc] initWithObject: @{@"id": @(1), @"name" : @"Name 1"} equalComparator:eq hashBlock:hash],
                        [[Wrapper alloc] initWithObject: @{@"id": @(2), @"name" : @"Name 2"} equalComparator:eq hashBlock:hash],
                        [[Wrapper alloc] initWithObject: @{@"id": @(3), @"name" : @"Name 3"} equalComparator:eq hashBlock:hash]];

NSArray *arrUpdated = @[[[Wrapper alloc] initWithObject: @{@"id": @(1), @"name" : @"Name 1 has Changed"} equalComparator:eq hashBlock:hash],
                        [[Wrapper alloc] initWithObject: @{@"id": @(2), @"name" : @"Name 2 has Changed"} equalComparator:eq hashBlock:hash],
                        [[Wrapper alloc] initWithObject: @{@"id": @(4), @"name" : @"Name 4"} equalComparator:eq hashBlock:hash]];

NSSet *setCurrent = [NSSet setWithArray:arrCurrent];
NSSet *setUpdated = [NSSet setWithArray:arrUpdated];
NSMutableSet *setFinal = [setUpdated mutableCopy];
[setFinal unionSet:setCurrent];

NSArray *arrFinal = [setFinal valueForKey:@"object"];

显示到目前为止的代码。请参考vikingosegundo答案。这是可接受的答案。此代码不给出答案。请取消勾选,否则将给出减号。此部分的结果是-({id=1;name=“Name1已更改”;},{id=2;name=“Name2已更改”;},{id=4;name=“Name4是一个新项目”;})这就是为什么我说我没有测试它,让询问者修改它。也许他修改了它,并且能够得到正确的答案。我已经更新了我的答案,并使用了我以前的代码。正如你所看到的,它非常有效。因为我证明你错了,所以对我过去的答案投了反对票?@用户3182143人们可能会喜欢我的代码而不是你的代码的一个原因是:你的代码过于复杂。即使用if和else语句嵌套循环。这意味着,对于
for
if
else
break
的每次调用,代码中的执行路径都会发生变化,从而增加复杂性和出错空间。另一方面,我的代码只使用高级抽象。(事实上,only if语句是在包装器init中找到的,并且比必需的语句更为常规)。如果您查看我的最后一个代码块:无论您如何更改输入数组,以下代码执行路径保持不变。