1

我有一个包含 的各种实例的数组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];
    }
}

有没有更好的(我不敢说更有效)的方式来做到这一点?

4

5 回答 5

3

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

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

要编写更少的代码,您可以编写for如下:

for (MyClass *myClass in myMutableArray) {

如果您仍然需要经常访问单个项目,您可能希望不再使用阵列进行存储。

另外,不要这样做:

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

因为您不必要地创建了一个您从不使用并且只是被丢弃的实例。

于 2013-07-25T19:51:03.727 回答
2

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

一种替代方法是将实例保存在NSMutableDictionarykey 是NSNumber. id然后,当您需要更新特定的实例时,您可以直接使用[myMutableDictionary objectForKey:@(someIntId)]. 这会将您的 O(n) 循环变成 O(1) 哈希表查找[假设一个好的hash实现,否则在最坏的情况下它将是 O(log n)]。

于 2013-07-25T19:47:37.850 回答
2

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

最终代码:

for (MyClass *myClass in myMutableArray)
{
    if(myClass.id == 5)
    {
        myClass.valueA = 100;
        myClass.valueB = 200;
        myClass.valueC = 300;
    }
}
于 2013-07-25T19:54:23.460 回答
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];
}
于 2013-07-25T20:00:57.523 回答
0

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

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

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
    }

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

于 2013-07-30T15:33:06.243 回答