检查两个 NSArray 是不是包含彼此的对象 (NSManagedObject)
Posted
技术标签:
【中文标题】检查两个 NSArray 是不是包含彼此的对象 (NSManagedObject)【英文标题】:Check two NSArrays for containing each other's objects (NSManagedObject)检查两个 NSArray 是否包含彼此的对象 (NSManagedObject) 【发布时间】:2012-02-14 16:12:11 【问题描述】:我已经被以下问题困扰了很长一段时间了: 我有两个 NSArray,都包含 NSManagedObject 子类对象。 它们由不同的来源提供,但其中的对象仍然具有相同的属性/值。 我现在要做的是检查数组 A 是否包含数组 B 中的对象,反之亦然。 不幸的是,NSArray 的 containsObject 方法似乎在这里不起作用。 我认为它使用 id-testing 对每个对象进行相等性检查,不是吗?
那么,有人知道要尝试什么吗?
我什至尝试将我的对象封装在 NSSets 中,使用 member: 作为我的比较方法,但这也没有奏效,特别是因为 NSManagedObject 子类的“你不能覆盖”isEqual 等。
这是一个代码sn-p:
//manufacturers is an array, parsed out of some xml here...
for(Manufacturer *manu in [fetchedResultsController fetchedObjects])
if(![manufacturers containsObject:manu])
NSLog(@"Deleting %@", manu.name);
[self.mContext deleteObject:manu];
for(Manufacturer *manu in manufacturers)
if(![[fetchedResultsController fetchedObjects] containsObject:manu])
NSLog(@"Adding %@", manu.name);
[newArray addObject:manu];
提前感谢任何提示;)
【问题讨论】:
【参考方案1】:我不确定这是否有效,但您可以尝试将您获得的字典与dictionaryWithValuesForKeys:
匹配。
类似这样的:
NSArray *keysToCompare = [NSArray arrayWithObjects:@"FooAttribute", @"BarAttribute", nil];
// create an array with the dictionary representation of the managedObject
NSMutableArray *fetchedObjectsDictionaries = [NSMutableArray arrayWithCapacity:[[fetchedResultsController fetchedObjects] count]];
for (NSManagedObject *object in [fetchedResultsController fetchedObjects])
NSDictionary *dictionaryRepresentation = [object dictionaryWithValuesForKeys:keysToCompare];
[fetchedObjectsDictionaries addObject:dictionaryRepresentation];
// another array with dictionaries for managedObjects
NSMutableArray *manufacturersDictionaries = [NSMutableArray arrayWithCapacity:[manufacturers count]];
for (NSManagedObject *object in manufacturers)
NSDictionary *dictionaryRepresentation = [object dictionaryWithValuesForKeys:keysToCompare];
[manufacturersDictionaries addObject:dictionaryRepresentation];
// compare those dictionaries
for (NSInteger i = 0; i < [fetchedObjectsDictionaries count]; i++)
NSDictionary *dictionary = [fetchedObjectsDictionaries objectAtIndex:i];
if (![manufacturersDictionaries containsObject:dictionary])
// get the corresponding managedObject
NSManagedObject *object = [[fetchedResultsController fetchedObjects] objectAtIndex:i];
[newArray addObject:object];
如果这不起作用,您可以编写自己的 isEqualToManufacturer:
方法并手动枚举数组。
【讨论】:
如果这些数组包含多个对象,这将非常昂贵且缓慢。【参考方案2】:您可以检查 3 种相等类型:相同的内存地址、托管对象 id 相等和值相等。您当前的代码已经检查对象是否共享相同的内存地址,这很可能不是您感兴趣的。这留下了两种可能的选择。使用托管对象 id 相等方法,您可以检查制造商是否指向数据库中的同一行。使用值相等,您可以根据共享值检查两个制造商是否相等。下面是一种检查 NSManagedObjectID 是否相等的方法。
for(Manufacturer *manu in [fetchedResultsController fetchedObjects])
id databaseIDTest = ^(Manufacturer * checkManu, NSUInteger idx, BOOL *stop)
return [[checkManu objectID] isEqual:[manu objectID]];
;
if([manufacturers indexOfObjectPassingTest:databaseIDTest] == NSIndexNotFound)
NSLog(@"Deleting %@", manu.name);
[self.mContext deleteObject:manu];
for(Manufacturer *manu in manufacturers)
id databaseIDTest = ^(Manufacturer * checkManu, NSUInteger idx, BOOL *stop)
return [[checkManu objectID] isEqual:[manu objectID]];
;
NSArray * fetchedObjects = [fetchedResultsController fetchedObjects];
if([fetchedObjects indexOfObjectPassingTest:databaseIDTest] == NSIndexNotFound)
NSLog(@"Adding %@", manu.name);
[newArray addObject:manu];
【讨论】:
这并不完全正确。由于您处于相同的上下文中,因此比较两个指针(内存地址)和比较两个托管对象 ID 可以有效地做同样的事情,但比较两个指针要便宜 很多(数量级)。 非常感谢您的回答,但这似乎也不起作用......认为我可能不得不手动迭代我的数组并计算出现次数。至少这是我能想到的以“我的方式”测试对象的唯一方法。【参考方案3】:您需要覆盖 -isEqual:
,因为这是 -[NSArray containsObject:]
调用的内容:
- (BOOL)isEqual:(id)other;
if (![other isKindOfClass:[Manufacturer class]])
return NO;
Manufacturer *otherManufacturer = other;
return ([self.name isEqual:otherManufacturer.name] &&
...
);
检查 NSSet 中的包含成本更低(如果遇到性能问题,这可能是有意义的)。它只有在你有一个相对不错的-hash
实现时才有效,但它很容易像这样实现:
- (NSUInteger)hash;
return [self.name hash] + [self.foo hash] + ...;
不要对哈希处理太多麻烦,只需使用 2 - 3 个最有可能的值来唯一标识对象。
【讨论】:
我希望能够简单地覆盖我的对象的比较方法,但由于我使用的是 NSManagedObject 子类,所以我不能。否则这肯定是最好的解决方案;)以上是关于检查两个 NSArray 是不是包含彼此的对象 (NSManagedObject)的主要内容,如果未能解决你的问题,请参考以下文章
搜索字符串是不是包含来自 Nsdictionary 的 NSArray 的任何值