objective-c 使用 NSMutableArray 的二维数组

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/724772/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 21:22:28  来源:igfitidea点击:

2D arrays using NSMutableArray

objective-ccocoacocoa-touchmultidimensional-arraynsmutablearray

提问by Ilya Suzdalnitski

I need to create a mutable two-dimensional array in Objective-C.

我需要在 Objective-C 中创建一个可变的二维数组。

For example I have:

例如我有:

NSMutableArray *sections;
NSMutableArray *rows;

Each item in sectionsconsists of an array rows. rowsis an array that contains objects.

中的每一项sections都由一个数组组成rowsrows是一个包含对象的数组。

And I want to do something like this:

我想做这样的事情:

[ sections[i] addObject: objectToAdd]; //I want to add a new row

In order have something like this: section 0, rows: obj1, obj2, obj3 section 1, rows: obj4, obj5, obj6, obj 7...

为了有这样的东西:第0节,行:obj1,obj2,obj3第1节,行:obj4,obj5,obj6,obj 7 ...

Is there a way to do that in Objective-C?

有没有办法在 Objective-C 中做到这一点?

回答by mouviciel

First, you must allocate and initialize your objects before use, something like: NSMutableArray * sections = [[NSMutableArray alloc] initWithCapacity:10];For the rows, you need one object for each, not a single NSMutableArray * rows;

首先,您必须在使用前分配和初始化对象,例如:NSMutableArray * sections = [[NSMutableArray alloc] initWithCapacity:10];对于行,每个行需要一个对象,而不是单个对象NSMutableArray * rows;

Second, depending on whether you're using Xcode 4.4+ (which introduced subscripting, a.k.a section[i]& section[i] = …) you may have to use [sections objectAtIndex:i]for reading and [section replaceObjectAtIndex:i withObject: objectToAdd]for writing.

其次,取决于您是否使用 Xcode 4.4+(它引入了下标,又名section[i]& section[i] = …),您可能必须使用它[sections objectAtIndex:i]来读取和[section replaceObjectAtIndex:i withObject: objectToAdd]写入。

Third, an array cannot have holes, i.e., obj1, nil, obj2. You must provide actual object to every index. If you do need to put nothing, you can use NSNullobject.

第三,数组不能有空洞,即obj1、nil、obj2。您必须为每个索引提供实际对象。如果你确实需要什么都不放,你可以使用NSNullobject.

Moreover, don't forget that you can also store Objective-C objects in plain C arrays:

此外,不要忘记您还可以将 Objective-C 对象存储在普通 C 数组中:

id table[lnum][rnum];
table[i][j] = myObj;

回答by Alex Rozanski

If you want to do this using arrays, you can intialize your sectionsarray, then add a rows array as follows:

如果要使用数组执行此操作,可以初始化sections数组,然后按如下方式添加行数组:

NSMutableArray *sections = [[NSMutableArray alloc] init];
NSMutableArray *rows = [[NSMutableArray alloc] init];
//Add row objects here

//Add your rows array to the sections array
[sections addObject:rows];

If you want to add this rows object at a certain index, use the following:

如果要在某个索引处添加此行对象,请使用以下命令:

//Insert your rows array at index i
[sections insertObject:rows atIndex:i];

You can then modify this rows array by retrieving the array:

然后,您可以通过检索数组来修改此行数组:

//Retrieve pointer to rows array at index i
NSMutableArray *rows = [sections objectAtIndex:i]
//modify rows array here

You could always create your own class called Section, which has an NSMutableArraymember called rows; then you store your rows inside this array, and store the Sectionobjects in an array:

你总是可以创建你自己的类Section,它有一个NSMutableArray名为rows;的成员。然后将行存储在此数组中,并将Section对象存储在数组中:

@interface Section : NSObject {
    NSMutableArray *rows;
}

Then you simply create Sectionitems, and you can create methods inside your class to add/remove row items. Then you package all the Sectionsitems up inside another array:

然后您只需创建Section项目,您就可以在您的类中创建方法来添加/删除行项目。然后将所有Sections项目打包到另一个数组中:

Section *aSection = [[Section alloc] init];
//add any rows to your Section instance here

NSMutableArray *sections = [[NSMutableArray alloc] init];
[sections addObject:aSection];

This becomes more useful if you want to add more properties for each Sectioninstance.

如果您想为每个Section实例添加更多属性,这将变得更加有用。

回答by Hyman Nutting

The language has no support for multi-dimensional object-oriented arrays, but you can make a class that does it using an NSMutableArray full of NSMutableArrays, like the following. I haven't tried compiling this or anything, I just typed it in.

该语言不支持多维面向对象的数组,但您可以使用一个包含 NSMutableArray 的 NSMutableArray 来创建一个类,如下所示。我没有尝试编译这个或任何东西,我只是输入它。

@interface SectionArray : NSObject {
  NSMutableArray *sections;
}
- initWithSections:(NSUInteger)s rows:(NSUInteger)r;
+ sectionArrayWithSections:(NSUInteger)s rows:(NSUInteger)r;
- objectInSection:(NSUInteger)s row:(NSUInteger)r;
- (void)setObject:o inSection:(NSUInteger)s row:(NSUInteger)r;
@end
@implementation SectionArray
- initWithSections:(NSUInteger)s rows:(NSUInteger)r {
  if ((self = [self init])) {
    sections = [[NSMutableArray alloc] initWithCapacity:s];
    NSUInteger i;
    for (i=0; i<s; i++) {
      NSMutableArray *a = [NSMutableArray arrayWithCapacity:r];
      for (j=0; j<r; j++) {
        [a setObject:[NSNull null] atIndex:j];
      }
      [sections addObject:a];
    }
  }
  return self;
}
+ sectionArrayWithSections:(NSUInteger)s rows:(NSUInteger)r {
  return [[[self alloc] initWithSections:s rows:r] autorelease];
}
- objectInSection:(NSUInteger)s row:(NSUInteger)r {
  return [[sections objectAtIndex:s] objectAtIndex:r];
}
- (void)setObject:o inSection:(NSUInteger)s row:(NSUInteger)r {
  [[sections objectAtIndex:s] replaceObjectAtIndex:r withObject:0];
}
@end

You'd use it like this:

你会像这样使用它:

SectionArray *a = [SectionArray arrayWithSections:10 rows:5];
[a setObject:@"something" inSection:4 row:3];
id sameOldSomething = [s objectInSection:4 row:3];

回答by Matt Mc

what the hell. As long as we're reviving this question, here's something for the age of literal collection syntax and visual format interpretation!

搞什么鬼。只要我们重新提出这个问题,这里就是文字集合语法和视觉格式解释时代的东西!

In case anyone is wondering, this works:

如果有人想知道,这有效:

NSMutableArray *multi = [@[ [@[] mutableCopy] , [@[] mutableCopy] ] mutableCopy];
multi[1][0] = @"Hi ";
multi[1][1] = @"There ";
multi[0][0] = @"Oh ";
multi[0][1] = @"James!";        
NSLog(@"%@%@%@%@", multi[0][0], multi[1][0], multi[1][1], multi[0][1]);

Result: "Oh Hi There James!"

结果:“哦,嗨,詹姆斯!”

Of course, there is the problem of trying something like multi[3][5] = @"?"and getting an invalid index exception, so I wrote a category for NSMutableArray.

当然,尝试类似的东西会multi[3][5] = @"?"出现索引无效异常的问题,所以我为NSMutableArray写了一个类别。

@interface NSMutableArray (NullInit)
+(NSMutableArray *)mutableNullArrayWithSize:(NSUInteger)size;
+(NSMutableArray *)mutableNullArraysWithVisualFormat:(NSString *)string;
@end

@implementation NSMutableArray (NullInit)

+(NSMutableArray *)mutableNullArrayWithSize:(NSUInteger)size
{
    NSMutableArray *returnArray = [[NSMutableArray alloc] initWithCapacity:size];
    for (int i = 0; i < size; i++) {
        [returnArray addObject:[NSNull null]];
    }
    return returnArray;
}

+(NSMutableArray *)mutableNullArraysWithVisualFormat:(NSString *)string
{
    NSMutableArray *returnArray = nil;
    NSRange bitRange;
    if ((bitRange = [string rangeOfString:@"^\[\d+]" options:NSRegularExpressionSearch]).location != NSNotFound) {
        NSUInteger size = [[string substringWithRange:NSMakeRange(1, bitRange.length - 2)] integerValue];
        if (string.length == bitRange.length) {
            returnArray = [self mutableNullArrayWithSize:size];
        } else {
            returnArray = [[NSMutableArray alloc] initWithCapacity:size];
            NSString *nextLevel = [string substringWithRange:NSMakeRange(bitRange.length, string.length - bitRange.length)];
            NSMutableArray *subArray;
            for (int i = 0; i < size; i++) {
                subArray = [self mutableNullArraysWithVisualFormat:nextLevel];
                if (subArray) {
                    [returnArray addObject:subArray];
                } else {
                    return nil;
                }
            }
        }
    } else {
        return nil;
    }
    return returnArray;
}

@end

As you can see, we have a convenience method for making an array full of NSNullso that you can set indices with wild abandon.

如您所见,我们有一个方便的方法来使数组充满 ,NSNull以便您可以随意设置索引。

Secondly, there's a recursive method that parses a string with a visual format like: [3][12](3 x 12 array). If your string is invalid in some way the method will return nil, but if it's valid you get a whole multidimensional array of the sizes you specify.

其次,有一种递归方法可以解析具有以下视觉格式的字符串:[3][12](3 x 12 数组)。如果您的字符串以某种方式无效,该方法将返回nil,但如果它有效,您将获得您指定大小的整个多维数组。

Here are some examples:

这里有些例子:

NSMutableArray *shrub = [NSMutableArray mutableNullArrayWithSize:5];
NSMutableArray *tree = [NSMutableArray mutableNullArraysWithVisualFormat:@"[3][12]"]; // 2-Dimensional Array
NSMutableArray *threeDeeTree = [NSMutableArray mutableNullArraysWithVisualFormat:@"[3][5][6]"]; // 3-Dimensional Array
NSMutableArray *stuntedTree = [NSMutableArray mutableNullArraysWithVisualFormat:@"[6][4][k]"]; // Returns nil

You can pass as many dimensions as you like into the visual format method, and then access them with the literal syntax, like so:

您可以将任意数量的维度传递到可视化格式方法中,然后使用文字语法访问它们,如下所示:

NSMutableArray *deepTree = [NSMutableArray mutableNullArraysWithVisualFormat:@"[5][3][4][2][7]"];
deepTree[3][2][1][0][5] = @"Leaf";
NSLog(@"Look what's at 3.2.1.0.5: %@", deepTree[3][2][1][0][5]);

Anyway, did this more as an exercise than anything else; it's probably pretty efficient in the grand scheme of things...considering as how we're making multi-dimensional arrays of Objective-C object pointers.

无论如何,这更像是一种练习,而不是其他任何事情;它在宏伟的计划中可能非常有效......考虑到我们如何制作Objective-C对象指针的多维数组。

回答by REDXD88

Thanks to Hyman for his code , i worked on it a bit; i need a multidimensional nsmutablearray for strings in one of my project , it still has some things that need to be fixed but works strings only at the moment , i will post it here , i am open for suggestions please cause i am only just a beginner in objective c at the moment...

感谢 Hyman 的代码,我做了一些工作;我的一个项目中需要一个用于字符串的多维 nsmutablearray ,它仍然有一些需要修复的东西,但目前仅适用于字符串,我会在这里发布它,我愿意接受建议,请因为我只是一个初学者目前在目标 c 中...

@interface SectionArray : NSObject {

  NSMutableArray *sections;    

}
- initWithSections:(NSUInteger)intSections:(NSUInteger)intRow;
+ sectionArrayWithSections:(NSUInteger)intSections:(NSUInteger)intRows;
- objectInSection:(NSUInteger)intSection:(NSUInteger)intRow;
- (void)setObject:(NSString *)object:(NSUInteger)intSection:(NSUInteger)intRow;
@end

@implementation SectionArray

- initWithSections:(NSUInteger)intSections:(NSUInteger)intRow {
    NSUInteger i;
    NSUInteger j;

    if ((self = [self init])) {
        sections = [[NSMutableArray alloc] initWithCapacity:intSections];
        for (i=0; i < intSections; i++) {
            NSMutableArray *a = [NSMutableArray arrayWithCapacity:intRow];
            for (j=0; j < intRow; j++) {
                [a insertObject:[NSNull null] atIndex:j];
            }
            [sections addObject:a];
        }
    }
    return self;    
}
- (void)setObject:(NSString *)object:(NSUInteger)intSection:(NSUInteger)intRow {
    [[sections objectAtIndex:intSection] replaceObjectAtIndex:intRow withObject:object];
}
- objectInSection:(NSUInteger)intSection:(NSUInteger)intRow {
    return [[sections objectAtIndex:intSection] objectAtIndex:intRow];
}
+ sectionArrayWithSections:(NSUInteger)intSections:(NSUInteger)intRows {
    return [[self alloc] initWithSections:intSections:intRows] ;
}
@end

This is working fine !!!

这工作正常!!!

i am currently using it like this

我目前正在像这样使用它

SectionArray *secA = [[SectionArray alloc] initWithSections:2:2];
[secA setObject:@"Object":0:0];
[secA setObject:@"ObjectTwo":0:1];
[secA setObject:@"ObjectThree":1:0];
[secA setObject:@"ObjectFour":1:1];

NSString *str = [secA objectInSection:1:1];

NSLog(@" object is = %@" , str);

Thanks again Hyman !!

再次感谢Hyman!!

回答by Matt Cooper

Reviving an old thread, but I reworked Hyman's code so 1. it compiles and 2. it is in the order of 2D c arrays [rows][columns] instead of [sections(columns)][rows] as he has it. Here you go!

恢复旧线程,但我重新编写了 Hyman 的代码,因此 1. 它可以编译并且 2. 它的顺序是 2D c 数组 [rows][columns] 而不是 [sections(columns)][rows],因为他拥有它。干得好!

TwoDArray.h:

TwoDArray.h:

#import <Foundation/Foundation.h>

@interface TwoDArray : NSObject

@property NSMutableArray *rows;

- initWithRows:(NSUInteger)rows columns:(NSUInteger)columns;
+ sectionArrayWithRows:(NSUInteger)rows columns:(NSUInteger)columns;
- objectInRow:(NSUInteger)row column:(NSUInteger)column;
- (void)setObject:(id)obj inRow:(NSUInteger)row column:(NSUInteger)column;

@end

TwoDArray.m:

TwoDArray.m:

#import "TwoDArray.h"

@implementation TwoDArray

- (id)initWithRows:(NSUInteger)rows columns:(NSUInteger)columns {
    if ((self = [self init])) {
        self.rows = [[NSMutableArray alloc] initWithCapacity: rows];
        for (int i = 0; i < rows; i++) {
            NSMutableArray *column = [NSMutableArray arrayWithCapacity:columns];
            for (int j = 0; j < columns; j++) {
                [column setObject:[NSNull null] atIndexedSubscript:j];
            }
            [self.rows addObject:column];
        }
    }
    return self;
}
+ (id)sectionArrayWithRows:(NSUInteger)rows columns:(NSUInteger)columns {
    return [[self alloc] initWithRows:rows columns:columns];
}
- (id)objectInRow:(NSUInteger)row column:(NSUInteger)column {
    return [[self.rows objectAtIndex:row] objectAtIndex:column];
}
- (void)setObject:(id)obj inRow:(NSUInteger)row column:(NSUInteger)column {
    [[self.rows objectAtIndex:row] replaceObjectAtIndex:column withObject:obj];
}
@end

回答by Matt Cooper

FYI: Hyman's code needs a bunch of work before it works. Among other issues, the autorelease can cause the data to get released before you access it and his usage calls the class method arrayWithSections:rows: when it is actually defined as sectionArrayWithSections:rows:

仅供参考:Hyman 的代码需要大量工作才能生效。除其他问题外,自动释放会导致数据在您访问它之前被释放,并且他的用法调用类方法 arrayWithSections:rows: 当它实际定义为 sectionArrayWithSections:rows 时:

I may try to post actual working code later if I get a chance.

如果有机会,我可能会稍后尝试发布实际的工作代码。

回答by Mantvydas

This is what I did in order to initialize array of arrays.

这就是我为了初始化数组而做的事情。

NSMutableArray *arrayOfArrays = [[NSMutableArray alloc] initWithCapacity:CONST];

for (int i=0; i<=CONST; i++) {
    [arrayOfArrays addObject:[NSMutableArray array]];
}

Then later in a code I could simply:

然后在代码中我可以简单地:

[[arrayOfArrays objectAtIndex:0] addObject:myObject];