我有两个这样的词典数组
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";
}];
我的要求是根据以下条件合并这两个数组
1)如果arrUpdated包含新项目(具有新 id 的项目),则应将其添加为新项目。
2)如果arrUpdated包含具有相同 id 的arrCurrent的项目,则应使用更新的项目替换这些项目
所以,最终的数组应该是这样的
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 = arrUpdated
arrFilteredSectors = 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];
}
答案 0 :(得分:1)
某些Set操作的时间。
hardes部分是我们需要给出我们使用的集合,理解对象是相同和相同的。
没有字典,但我们可以引入一个包装类来使用它的实现。
@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"];
答案 1 :(得分:-1)
我认为循环可以做到这一点。
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]]
}
}
虽然你也可以使用谓词。
我没有测试过此代码,因为我没有机器。但你至少可以修改它。
更新:
我最终找到了一台机器来证明我的代码是有效的。使用提问者提供的测试数据:
NSMutableArray *arrCurrent = [NSMutableArray arrayWithArray:@[@{
@"id":@"1", @"name":@"Name1"
},@{
@"id":@"2", @"name":@"Name2"
},@{
@"id":@"3", @"name":@"Name3"
}]];
NSMutableArray *arrUpdated = [NSMutableArray arrayWithArray:@[@{
@"id":@"1", @"name":@"Name1 has changed"
},@{
@"id":@"2", @"name":@"Name2 has changed"
},@{
@"id":@"4", @"name":@"Name4 is a new item"
}]];
for(int x=0;x<[arrUpdated count];x++){
//condition 2
if([[arrCurrent valueForKey:@"id"] containsObject:[[arrUpdated objectAtIndex:x] valueForKey:@"id"]]){
//start updating current array
for(int y=0;y<[arrCurrent count];y++){
if([[[arrCurrent objectAtIndex:y] valueForKey:@"id"] isEqualToString:[[arrUpdated objectAtIndex:x] valueForKey:@"id"]]){
NSLog(@" (%@) will change to (%@)",[[arrCurrent objectAtIndex:y] valueForKey:@"name"],[[arrUpdated objectAtIndex:x] valueForKey:@"name"]);
[arrCurrent replaceObjectAtIndex:y withObject:[arrUpdated objectAtIndex:x] ];
break;
}
}
}
//condition 1
else{
[arrCurrent addObject: [arrUpdated objectAtIndex:x]];
}
}
NSLog(@"RESULT>: %@",arrCurrent);
结果:&gt;&gt;
2015-06-04 23:24:30.949 dd[7523:60b] (Name1) will change to (Name1 has changed)
2015-06-04 23:24:30.950 dd[7523:60b] (Name2) will change to (Name2 has changed)
2015-06-04 23:24:30.951 dd[7523:60b] RESULT>: (
{
id = 1;
name = "Name1 has changed";
},
{
id = 2;
name = "Name2 has changed";
},
{
id = 3;
name = Name3;
},
{
id = 4;
name = "Name4 is a new item";
}
)