Question

J'ai un NSArray et j'aimerais créer un nouveau NSArray avec des objets du tableau d'origine qui répondent à certains critères. Le critère est décidé par une fonction qui retourne un BOOL .

Je peux créer un NSMutableArray , parcourir le tableau source, copier les objets acceptés par la fonction de filtrage, puis en créer une version immuable.

Y a-t-il un meilleur moyen?

Était-ce utile?

La solution

NSArray et NSMutableArray fournissent des méthodes pour filtrer le contenu d'un tableau. NSArray fournit filterArrayUsingPredicate: qui renvoie un nouveau tableau contenant les objets du récepteur qui correspondent au prédicat spécifié. NSMutableArray ajoute filterUsingPsingicate: , qui évalue le contenu du destinataire par rapport au prédicat spécifié et ne conserve que les objets correspondants. Ces méthodes sont illustrées dans l'exemple suivant.

NSMutableArray *array =
    [NSMutableArray arrayWithObjects:@"Bill", @"Ben", @"Chris", @"Melissa", nil];

NSPredicate *bPredicate =
    [NSPredicate predicateWithFormat:@"SELF beginswith[c] 'b'"];
NSArray *beginWithB =
    [array filteredArrayUsingPredicate:bPredicate];
// beginWithB contains { @"Bill", @"Ben" }.

NSPredicate *sPredicate =
    [NSPredicate predicateWithFormat:@"SELF contains[c] 's'"];
[array filteredArrayUsingPredicate:sPredicate];
// array now contains { @"Chris", @"Melissa" }

Autres conseils

Il existe une foule de façons de faire cela, mais de loin le plus simple est sûrement d'utiliser [NSPredicate predicateWithBlock:] :

NSArray *filteredArray = [array filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id object, NSDictionary *bindings) {
    return [object shouldIKeepYou];  // Return YES for each object you want in filteredArray.
}]];

Je pense que c'est à peu près aussi concis que possible.

Swift:

Pour ceux qui travaillent avec des NSArray dans Swift, vous préférerez peut-être cette même plus version concise:

nsArray = nsArray.filter { <*>.shouldIKeepYou() }

filtre est simplement une méthode sur Array ( NSArray est implicitement ponté vers Swift & # 8217; s Array ). Cela prend un argument: une fermeture qui prend un objet dans le tableau et retourne un Bool . Dans votre clôture, il vous suffit de renvoyer true pour tous les objets de votre choix dans le tableau filtré.

Si vous utilisez OS X 10.6 / iOS 4.0 ou une version ultérieure, vous êtes probablement mieux avec des blocs que NSPredicate. Voir - [NSArray indexesOfObjectsPassingTest :] ou créez votre propre catégorie pour ajouter une méthode pratique -select: ou -filter: ( exemple ).

Vous voulez que quelqu'un d'autre écrive cette catégorie, la teste, etc.? Consultez BlocksKit ( documents de tableau ). Et il y a beaucoup d'autres exemples à trouver, par exemple en recherchant par exemple. " ns catégorie de bloc sélectionnez " .

D'après une réponse de Clay Bridges, voici un exemple de filtrage à l'aide de blocs (changez yourArray en nom de variable de tableau et testFunc en nom de votre fonction de test ):

yourArray = [yourArray objectsAtIndexes:[yourArray indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
    return [self testFunc:obj];
}]];

En supposant que vos objets soient tous d'un type similaire, vous pouvez ajouter une méthode en tant que catégorie de leur classe de base qui appelle la fonction que vous utilisez pour vos critères. Créez ensuite un objet NSPredicate faisant référence à cette méthode.

Dans certaines catégories, définissez votre méthode qui utilise votre fonction

@implementation BaseClass (SomeCategory)
- (BOOL)myMethod {
    return someComparisonFunction(self, whatever);
}
@end

Puis, où que vous filtriez:

- (NSArray *)myFilteredObjects {
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"myMethod = TRUE"];
    return [myArray filteredArrayUsingPredicate:pred];
}

Bien sûr, si votre fonction ne compare que les propriétés accessibles depuis votre classe, il sera peut-être plus simple de convertir les conditions de la fonction en chaîne de prédicat.

NSPredicate est la méthode de construction suivante utilisée par nextstep pour filtrer une collection ( NSArray , NSSet , NSDictionary ).

Par exemple, considérons deux tableaux arr et filterarr :

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF contains[c] %@",@"c"];

filteredarr = [NSMutableArray arrayWithArray:[arr filteredArrayUsingPredicate:predicate]];

le filterarr aura sûrement les éléments qui contiennent le caractère c seul.

pour qu'il soit facile de se souvenir de ceux qui ont peu de fond SQL

*--select * from tbl where column1 like '%a%'--*

1) sélectionnez * dans tbl - > collection

2) column1, comme '% a%' - > NSPredicate * predicate = [NSPredicate predicateWithFormat: @ "SELF contient [c]% @", @, "c"];

3) sélectionnez * dans tbl où column1, tel que '% a%' - >

[NSMutableArray arrayWithArray:[arr filteredArrayUsingPredicate:predicate]];

J'espère que cela vous aidera

NSArray + X.h

@interface NSArray (X)
/**
 *  @return new NSArray with objects, that passing test block
 */
- (NSArray *)filteredArrayPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate;
@end

NSArray + X.m

@implementation NSArray (X)

- (NSArray *)filteredArrayPassingTest:(BOOL (^)(id obj, NSUInteger idx, BOOL *stop))predicate
{
    return [self objectsAtIndexes:[self indexesOfObjectsPassingTest:predicate]];
}

@end

Vous pouvez télécharger cette catégorie ici

Commander cette bibliothèque

https://github.com/BadChoice/Collection

Il contient de nombreuses fonctions de tableau faciles à ne jamais écrire une boucle

Vous pouvez donc simplement faire:

NSArray* youngHeroes = [self.heroes filter:^BOOL(Hero *object) {
    return object.age.intValue < 20;
}];

ou

NSArray* oldHeroes = [self.heroes reject:^BOOL(Hero *object) {
    return object.age.intValue < 20;
}];

La méthode la plus simple et la plus simple consiste à créer cette méthode et à transmettre un tableau et une valeur:

- (NSArray *) filter:(NSArray *)array where:(NSString *)key is:(id)value{
    NSMutableArray *temArr=[[NSMutableArray alloc] init];
    for(NSDictionary *dic in self)
        if([dic[key] isEqual:value])
            [temArr addObject:dic];
    return temArr;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top