【问题标题】:comparing arrays in objective-c比较objective-c中的数组
【发布时间】:2009-07-16 14:05:28
【问题描述】:

好的,一个非常简单的问题.. 在 c++ 中它似乎可以工作,但在 Objective-c 中我似乎很难解决:S .. 如果你想比较两个数组,应该是这样的吧

for ( int i = 0; i < [appdelegate.nicearray count]; i++ ) 
{ 
  if ( appdelegate.nicearray[i] == appdelegate.exercarray[i] )
  { 
     NSLog(@"the same elements in this selection");
  }
}

到底是什么问题?

【问题讨论】:

    标签: objective-c arrays cocoa compare


    【解决方案1】:

    这些是 Cocoa 数组对象(NSArray 的实例),而不是 C 数组或 C++ 向量,请记住,Objective-C 没有运算符重载。您可以对对象执行的唯一操作是传递它、将其存储在变量中并向其发送消息。

    所以数组下标运算符对于 Objective-C 对象来说是错误的。我认为取消引用指向 Objective-C 对象的指针在语言上甚至是无效的,所以这段代码应该会给你一个编译器错误。不过我可能记错了。如果它确实进入运行时,该代码迟早会崩溃,因为您正在访问超出数组对象末端的内存。

    (从 2013 年开始编辑:Objective-C 现在支持对象的下标。这最终会转化为适当的 objectAtIndex: 或 replaceObjectAtIndex:withObject: 消息。因此,问题中的代码现在实际上可以工作,尽管它仍然不是简单地遍历数组的正确方法,更不用说比较两个数组了。)

    通过索引从 NSArray 对象中检索对象的正确方法不是使用数组下标运算符,而是向数组对象发送objectAtIndex: 消息:

    [myArray objectAtIndex:i]
    

    迭代数组对象的元素的正确方法,假设你真的不需要其他东西的索引(例如替换可变数组中的对象),是直接循环它(这被称为“快速枚举”):

    for (MyObject *myObject in myArray) {
        …
    }
    

    NSArray 还响应objectEnumerator 和reverseObjectEnumerator,它们返回一个类似的可迭代对象。在这两者中,reverseObjectEnumerator 在新代码中更有用,因为您可以直接迭代数组以向前迭代。在快速枚举存在之前,它们都是最有用的;该代码如下所示:

    NSEnumerator *myArrayEnum = [myArray objectEnumerator];
    MyObject *myObject;
    while ((myObject = [myArrayEnum nextObject])) {
        …
    }
    

    (是的,这是条件中的一个赋值。故意的,因此额外的()。我们当时大胆地编码,不是吗?)

    不过,正如 Williham Totland 建议的那样,对于您正在做的事情,您更可能希望向其中一个数组发送 isEqualToArray: 消息:

    BOOL theyAreEqual = [myFirstArray isEqualToArray:mySecondArray];
    

    这将确保两个数组具有相同的长度,然后以锁步方式遍历它们,向每对对象发送isEqual:。如果每条isEqual: 消息都返回YES,它将返回YES; NO 否则。数组可能包含不同的对象,但只要每一对相等,数组本身就相等。

    假设你想要对象相等。如果其中一个对象在您向其发送isEqual: 消息并传递另一个对象时以YES 响应,则两个单独的对象是相等的。如果您打算比较对象的身份,那么您确实需要自己执行锁步循环并使用==:

    BOOL arraysContainTheSameObjects = YES;
    NSEnumerator *otherEnum = [otherArray objectEnumerator];
    for (MyObject *myObject in myArray) {
        if (myObject != [otherEnum nextObject]) {
            //We have found a pair of two different objects.
            arraysContainTheSameObjects = NO;
            break;
        }
    }
    

    但这不太可能。大多数时候,我想测试对象的相等性,而不是身份,所以isEqualToArray: 是我想要的。

    【讨论】:

    • 随机跟进问题:[nsArrrayInstance isEqual:otherInstance]是否等同于[nsArrrayInstance isEqualToArray:otherInstance]?
    • 所以归结为,第一个链接指出isEqualTo... 可能假设参数是正确的类型〜我不确定第二个链接正在讨论什么边缘情况。或许我可以麻烦您详细说明一下?
    • @nmr:“在 Cocoa 框架的所有 isEqualTo&lt;Type&gt;: 方法中,nil 不是有效参数,这些方法的实现可能会在收到 nil 时引发异常。然而,为了向后兼容,Cocoa 框架的isEqual: 方法确实接受nil,返回NO。”
    • @Peter Hosey 酷,谢谢。所以你会说所有这一切的一个必然结果是,如果你实现isEqualTo&lt;Type&gt;:,那么不实现isEqual: 会很奇怪吗?那么&lt;Type&gt; 类型的给定参数应该返回相同的值吗?
    【解决方案2】:

    您需要isEqualToArray: 方法。如:

    if ([arrayOne isEqualToArray:arrayTwo]) {
      // Do something
    }
    

    这将递归地比较两个数组,同时具有不需要不必要的迂回和不需要循环的优点。

    【讨论】:

      【解决方案3】:

      尝试告诉我们您在运行此代码时得到的结果。方法是正确的,但试试这个:

      for (int i =0; i< appdelegate.nicearray.count; i++)
      {
          if ([[appdelegate objectAtIndex:i] isEqual: [appdelegate.exercarray objectAtIndex:i]])
          {
              NSLog(@"the same");
          }
      }  
      

      【讨论】:

      • 您通常应该将对象与isEqual: 进行比较,而不是指针相等性。
      • 此外,您可以使用 isEqualToArray: 来执行此操作,正如 Williham Totland 建议的那样。 (提示他应该使用objectAtIndex: 而不是数组下标运算符。)
      【解决方案4】:

      这是我根据排名靠前的示例汇总的一个小示例。这只是检查数组是否包含相同的值,而不考虑顺序以及是否有任何重复。我主要使用它来比较两个字典的键(通常以各种排序顺序返回它们的 allKeys 数组),以查看它们是否包含相同的对象。感谢 Peter Hosley 提供了我从中改编的示例。

      #pragma mark - Arrays
      // Check to see if arrays contain the same elements, not necessarily in the same order
      // This is different from [array isEqualToArray:responseKeys] which demands the same order in both arrays
      // ## Does not compensate for duplicate entries in an array
      + (BOOL)doArraysContainTheSameObjects:(NSArray *)firstArray withArray:(NSArray *)secondArray {
          BOOL arraysContainTheSameObjects = YES;
      
          for (id myObject in firstArray) {
              if (![secondArray containsObject:myObject]) {
                  // We have found an object that is not in the other array.
                  arraysContainTheSameObjects = NO;
                  break;
              }
          }
          return arraysContainTheSameObjects;
      }
      

      【讨论】:

      • 说实话,如果要成为通用的,我们还应该检查第一个数组是否包含第二个数组中的所有对象。
      • 另外,如果 firstArray 为 nil,第二个数组为空数组,则上述方法将返回 true。
      【解决方案5】:

      比较数组时,我会执行以下操作:

      • 检查一个数组是否为 nil 而另一个不是
      • 检查长度是否相同
      • 对每个元素进行迭代(像您一样使用 for 循环),检查另一个数组中的匹配元素。

      要比较元素,您需要定义要视为“相等”的元素。是只有数组中的指针相等时才相等,还是内容也相等时才相等。

      对于指针的情况,可以使用==。

      对于深度比较,您可能需要使用 CompareTo 或类似的东西。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-17
        相关资源
        最近更新 更多