【问题标题】:Get the opposite of intersection between array A and array B获取数组 A 和数组 B 之间交集的相反数
【发布时间】:2014-03-11 15:16:31
【问题描述】:

快速提问。我有两个 NSMutableArray:

Array 1: [A,B,C,D,E,F];
Array 2: [B,E,F];

请注意,数组 2 始终是数组 1 的子集 - 表示存在的对象是数组 2,肯定存在的对象也是数组 1。

所以我想要构建一个数组,其中包含数组 2 中 NOT 的对象。就像这样

Array 3: [A,C,D];

我已尝试使用 this post 中所述的相对补码,但生成的数组与数组 1 基本相同。它不会消除数组 2 中存在的对象。

我也尝试了answer here,但仍然没有得到我想要的。除非我真的在做一些非常明显的错误。

我猜,使用 NSPredicate 更可取。但我对想法和提示持开放态度。

注意:仅出于上下文考虑,我这样做是为了更新我的 UITableView,主要是出于数据过滤的目的。

谢谢!


更新

所以到目前为止给出的所有答案实际上都适用于我的一组简单的虚拟数据。但是当我用我的真实数据进行测试时,创建的数组 3 仍然与数组 1 相同。所以,我将提供更多关于我的东西的信息。

两个数组都是存储字典对象的NSMutablArray。我实际上使用的是 Parse.com,所以两个数组中的对象都是PFObject(如果我没记错的话,这只是 NSObject)。我不知道这对任何事情有什么影响,但是是的,似乎不起作用。

当我尝试逐步完成该过程时,这是一个screenshot from the console

感谢到目前为止的帮助。

【问题讨论】:

  • 你完全改变了问题。你应该编辑它并解释你想要过滤数组的标准,特别是你想要比较的键。

标签: ios objective-c arrays uitableview


【解决方案1】:

这里没有必要沿着谓词路线走,你清楚地知道你想做什么,并且可以用简单的原生 API 来表达。

NSMutableArray *mArray3 = [NSMutableArray arrayWithArray:array1];
[mArray3 removeObjectsInArray:array2];

NSArray* array3 = [mArray3 copy];

需要注意的重要一点:

removeObjectsInArray:

此方法假定 otherArray 中的所有元素都响应 hash 和 isEqual:。

要使一个对象被视为相等,它们需要响应hashisEqual:,并且这些值要在两个相等的对象之间匹配。一篇关于平等的好文章can be read here

如果PFObject 简单地继承自NSObject,那么相等检查将是非常基础的。它会简单地通过询问“这些对象是否是同一个对象,基于内存中的位置?”来检查相等性。这可能解释了为什么您的虚拟数据有效,而真实数据却无效。

您需要将 PFObject 子类化以使其了解内容。这意味着您可以覆盖hashisEqual: 以提供更合理的平等声明。例如,“这些对象是同一个对象吗,基于 'name' 属性的值”。由你来定义什么使对象相等。

【讨论】:

  • 当我试用它时,它适用于简单的虚拟数据,但不适用于我的真实数据。如果有帮助,我用更多信息更新了这个问题。也许您可以提供更多见解。谢谢!
  • 您的真实数据不被视为“平等”。我会更新答案,但基本上你需要确保来自 hashisEqual: 的值与相等的对象匹配。
  • 感谢您提供额外信息。我会尝试一下。但由于最初的问题被认为已解决,我会接受你的回答,因为它绝对是最简单的。
【解决方案2】:

WDUK 的答案可能是要走的路,因为它更简单并且只需要一个新对象(加上该对象的副本)。但是,如果您喜欢离散数学,NSMutableSet 允许您执行集合操作。也就是说,您的问题的另一个(过于复杂,但非常具有描述性)答案是:

// convert arrays to sets. 
// since array2 is always a subset of array1, we don't need to create a union set.
NSMutableSet *set1 = [NSMutableSet setWithArray:array1];
NSSet *set2 = [NSSet setWithArray:array2];

// find intersecting objects
NSMutableSet *intersection = [NSMutableSet setWithSet:set1];
[intersection intersectSet:set2];

// remove intersecting objects (result: your desired set)
[set1 minusSet:intersection];

NSArray *nonIntersectingObjects = [set1 allObjects];

正如 WDUK 建议的那样,您的问题可以通过 NSMutableArray 轻松解决。但是,当出现类似但更复杂的问题时,集合操作可能会提供更简单、更优雅的解决方案。

【讨论】:

  • 我最初是这么想的,但是这个过程有能力移除排序,这是数组的核心属性。
  • 真实并且可能是一个非常重要的事实(NSSet 的每个定义都是无序的)。
  • 这里有 NSOrderedSet。
  • @RamyAlZuhouri 不过,数组允许重复。这可能是这里的要求,所以除非问题得到澄清,否则我们不能假设顺序和/或重复是无关紧要的。
  • 只是为了回答问题,不,顺序无关紧要。
【解决方案3】:

如果你想使用谓词来做到这一点,这是这样做的方法:

NSArray* array1= @[@'A',@'B',@'C',@'D',@'E',@'F'];
NSArray* array2= @[@'B',@'E',@'F'];
NSPredicate* predicate= [NSPredicate predicateWithFormat: @"not(self in %@)",array2];
NSArray* array3=[array1 filteredArrayUsingPredicate: predicate];

SELF 表示数组中的评估对象。 IN 运算符可用于检查集合中是否有任何对象,这里有一些参考:Predicate programming guide / aggregate operations

【讨论】:

  • 当我试用它时,它也适用于简单的虚拟数据,但不适用于我的真实数据。如果有帮助,我用更多信息更新了这个问题。也许您可以提供更多见解。谢谢!
猜你喜欢
  • 1970-01-01
  • 2011-06-18
  • 2022-12-23
  • 2023-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-18
  • 1970-01-01
相关资源
最近更新 更多