44 votes

Tableaux 2D dans l'objectif c

Comment puis-je modifier un tableau 2D dans l'objectif c? J'ai besoin de créer un mutable.

Par exemple j'ai:

 NSMutableArray *sections;
NSMutableArray *rows;
 

Chaque élément dans les sections est constitué de rangées de tableaux. Les lignes est un tableau qui contient des objets.

Et je veux faire quelque chose comme ça:

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

Pour avoir quelque chose comme ceci: section 0, rangées: obj1, obj2, obj3 section 1, rangées: obj4, obj5, obj6, obj 7 ...

Y a-t-il un moyen de le mettre en œuvre dans objectif-c?

88voto

mouviciel Points 36624

Tout d'abord, vous devez allouer et initialiser vos objets avant de les utiliser, quelque chose comme: NSMutableArray * sections = [[NSMutableArray alloc] initWithCapacity:10]; Pour les lignes, vous avez besoin d'un objet pour chacun d'eux, pas un seul NSMutableArray * rows;

Deuxièmement, selon que vous êtes en utilisant Xcode 4.4+ (qui a introduit subscripting, une.k.un section[i] & section[i] = …), vous pouvez utiliser [sections objectAtIndex:i] pour la lecture et l' [section replaceObjectAtIndex:i withObject: objectToAdd] pour l'écriture.

Troisièmement, un tableau ne peut pas avoir de trous, c'est à dire, obj1, néant, obj2. Vous devez fournir de l'objet réel à chaque index. Si vous avez besoin de mettre de rien, vous pouvez utiliser NSNull objet.

En outre, n'oubliez pas que vous pouvez également stocker Objective-C objets dans la plaine du C des tableaux:

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

17voto

Alex Rozanski Points 26107

Si vous voulez le faire à l'aide de tableaux, vous pouvez initialiser votre sections tableau, puis ajoutez les lignes de tableau comme suit:

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];

Si vous voulez ajouter ces lignes d'objet à une certaine index, utilisez la commande suivante:

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

Vous pouvez alors modifier ces lignes de la matrice par la récupération de la matrice:

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

Vous pouvez toujours créer votre propre classe appelée Section, ce qui a un NSMutableArray membre appelés rows; alors que vous rangez vos lignes à l'intérieur de cet ensemble, et de stocker l' Section objets dans un tableau:

@interface Section : NSObject {
    NSMutableArray *rows;
}

Ensuite, il vous suffit de créer Section articles, et vous pouvez créer des méthodes à l'intérieur de votre classe à ajouter/supprimer ligne des articles. Ensuite, vous créez un package de tous les Sections articles à l'intérieur d'un autre tableau:

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

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

Cela devient encore plus utile si vous voulez ajouter plus de propriétés pour chaque Section de l'instance.

9voto

Jack Nutting Points 418

Le langage ne prend pas en charge les tableaux multidimensionnels orientés objet, mais vous pouvez créer une classe qui le fait à l'aide d'un NSMutableArray complet de NSMutableArrays, comme ci-dessous. Je n'ai pas essayé de compiler ceci ou quoi que ce soit, je l'ai simplement tapé.

 @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
 

Vous l'utiliseriez comme ceci:

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

6voto

Matt Mc Points 1835

ce que l'enfer. Tant que nous sommes revivre cette question, voici quelque chose pour l'âge de littéral de la collection de la syntaxe et de la présentation visuelle de l'interprétation!

Dans le cas où quelqu'un se demande, cela fonctionne:

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]);

Résultat: "Oh Salut James!"

Bien sûr, il y a le problème d'essayer quelque chose comme multi[3][5] = @"?" et d'obtenir un index non valide exception, j'ai donc écrit une catégorie pour 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

Comme vous pouvez le voir, nous avons une méthode pratique pour faire un tableau complet de l' NSNull , de sorte que vous pouvez définir des indices avec abandon sauvage.

Deuxièmement, il y a une méthode récursive qui analyse une chaîne avec un format visuel comme: [3][12] (3 x 12 tableau). Si votre chaîne n'est pas valide en quelque sorte la méthode retournera nil, mais si elle est valide, vous obtenez un ensemble de tableau multidimensionnel de la taille que vous spécifiez.

Voici quelques exemples:

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

Vous pouvez passer autant de dimensions que vous aimez dans le format visuel de la méthode, puis d'y accéder avec la syntaxe littérale, comme suit:

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]);

De toute façon, ne présente plus comme un exercice que n'importe quoi d'autre, c'est assez efficace dans le grand schéma des choses...considérant que la façon dont nous faisons multi-dimensions des tableaux d'Objective-C pointeurs d'objet.

5voto

Jericho Points 51

Merci à Jack pour son code, j'ai un peu travaillé dessus; j'ai besoin d'un nsmutablearray multidimensionnel pour les chaînes dans l'un de mes projets, il a encore certaines choses à réparer mais les chaînes ne fonctionnent que pour le moment, je vais les poster ici, je suis ouvert aux suggestions s'il vous plaît car je ne suis qu'un débutant en objectif c pour le moment ...

 @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
 

Cela fonctionne bien !!!

je l'utilise actuellement comme ça

 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);
 

Merci encore Jack !!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X