通过属性查找数组中的特定实例

时间:2013-07-25 19:38:27

标签: objective-c cocoa-touch nsarray

我有一个包含MyClass的各种实例的数组,它有四个属性:int idint valueAint valueBint valueC。有时,我需要修改特定实例的属性(对于这个例子,假设它是id等于5的那个)。

目前我这样做:

MyClass *myClass = [[MyClass alloc] init];

for (int i = 0; i < [myMutableArray count]; i++)
{
    myClass = [myMutableArray objectAtIndex:i];

    if(myClass.id == 5)
    {
        myClass.valueA = 100;
        myClass.valueB = 200;
        myClass.valueC = 300;
        [myMutableArray replaceObjectAtIndex:i withObject: myClass];
    }
}

有没有更好的(我更犹豫要说更有效率)这样做的方式?

5 个答案:

答案 0 :(得分:3)

如果您知道只有1个id为5的实例,则只需在完成更新后在break;语句的末尾添加if。这将终止循环迭代并且可能是最有效的。

如果没有分析,你不应该过多担心运行时性能。

要编写更少的代码,您可以将for写为:

for (MyClass *myClass in myMutableArray) {

如果您无论如何都需要经常访问单个项目,您可能希望更改为使用阵列存储。

另外,不要这样做:

MyClass *myClass = [[MyClass alloc] init];

因为你不必要地创建了一个你从未使用过的实例而且被扔掉了。

答案 1 :(得分:2)

在开始过度优化之前,您确定这是性能瓶颈吗?

另一种方法是将实例保留在NSMutableDictionary,其中密钥为NSNumber的{​​{1}}。然后,当您需要更新特定的一个时,您可以直接使用id检索实例。这会将你的O(n)循环变成O(1)散列表查找[假设一个好的[myMutableDictionary objectForKey:@(someIntId)]实现,或者在最坏的情况下它将是O(log n)。

答案 2 :(得分:2)

我看到了两种快速优化代码的方法。首先,你需要对新对象进行原始赋值以替换数组中的myClass实例 - 因为它是一个指针,你实际上直接操作数组中的对象。其次,如果您使用增量器保留当前的for循环,则不需要原始分配的MyClass。你不需要对它进行alloc和init,因为你只需要一个指针。但是,您可以使用for循环而不是递增for循环并直接循环遍历数组。

最终代码:

for (MyClass *myClass in myMutableArray)
{
    if(myClass.id == 5)
    {
        myClass.valueA = 100;
        myClass.valueB = 200;
        myClass.valueC = 300;
    }
}

答案 3 :(得分:1)

根据任何标准获取数组中特定成员的简单方法虽然冗长,但使用indexOfObjectPassingTest:并结合objectAtIndex:

MyClass * theInstanceIWant;
theInstanceIWant = [myArray objectAtIndex:[dates indexOfObjectPassingTest:^BOOL (id obj, NSUInteger idx, BOOL *stop) {
                                                        return ([obj id] == 5);
                    }];

theInstanceIWant.valueA = 100;
theInstanceIWant.valueB = 200;
theInstanceIWant.valueC = 300;

无需使用replaceObjectAtIndex:withObject: - 名称theInstanceIWant指的是数组中的实际对象,您可以在数组中保留其属性时更改其属性。


(使用NSArray上的类别方法会更加愉快。)

- (id)WSSObjectPassingTest:(BOOL (^)(id obj, NSInteger idx, BOOL *stop))test
{
    NSUInteger testedIndex = [self indexOfObjectPassingTest:test];
    return [self objectAtIndex:testedIndex];
}

答案 4 :(得分:0)

首先,你永远不想在Objective-C中命名一个变量idid表示指向任何类型的指针,它是一个保留的关键字。

更好/更有效的方法称为快速枚举。快速枚举是迭代列表/数组/集中每个项的特殊方法。代码如下所示:

for (MyClass *iteratorObject in myMutableArray) {
    if (iteratorObject.id == 5) {
        //do what you want with that specific object
        //insert your modified object back into mutable array
    }

虽然这是最简单的方法,但你违反了一条规则。在阵列上执行快速枚举时,永远不应该编辑/添加/删除对象。我的解决方案是简单地调用返回immutableArray的[myMutableArray copy],然后遍历它。