it-swarm-eu.dev

filtrování NSArray do nového NSArray v cíli-c

Mám NSArray a rád bych vytvořil nový NSArray s objekty z původního pole, které splňují určitá kritéria. O kritériích rozhoduje funkce, která vrací BOOL.

Můžu vytvořit NSMutableArray, iterovat zdrojovým polem a kopírovat přes objekty, které filtrační funkce přijímá, a pak vytvořit jeho neměnnou verzi. 

Existuje lepší způsob?

110
lajos

NSArray a NSMutableArray poskytují metody filtrování obsahu pole. NSArray poskytuje checkedArrayUsingPredicate: , které vrací nové pole obsahující objekty v přijímači, které odpovídají zadanému predikátu. NSMutableArray přidá filterUsingPredicate: který vyhodnotí obsah přijímače proti zadanému predikátu a ponechá pouze objekty, které odpovídají. Tyto metody jsou ilustrovány v následujícím příkladu.

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" }
132
lajos

Existuje mnoho způsobů, jak toho dosáhnout, ale zdaleka nejkrásnější je jistě pomocí [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.
}]];

Myslím, že je to tak stručné, jak to jde.


Rychlý:

Pro ty, kteří pracují s NSArrays v Swift, můžete dávat přednost této ještě více stručné verzi:

nsArray = nsArray.filter { $0.shouldIKeepYou() }

filter je jen metoda Array (NSArray je implicitně přemostěna na Array Swift). To trvá jeden argument: uzavření, které vezme jeden objekt v poli a vrátí Bool. Ve svém uzávěru stačí vrátit true pro všechny objekty, které chcete v filtrovaném poli.

91
Stuart

Na základě odpovědi Clay Bridges je zde příklad filtrování pomocí bloků (změna yourArray na název proměnné pole a testFunc na název testovací funkce):

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

Za předpokladu, že vaše objekty jsou podobného typu, můžete přidat metodu jako kategorii své základní třídy, která volá funkci, kterou používáte pro svá kritéria. Potom vytvořte objekt NSPredicate, který odkazuje na tuto metodu.

V některých kategoriích definujte metodu, která používá vaši funkci

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

Pak budete kdekoli filtrovat:

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

Samozřejmě, pokud se vaše funkce porovnává pouze s vlastnostmi dosažitelnými z vaší třídy, může být jednodušší převést podmínky funkce na řetězec predikátu.

16
Ashley Clark

NSPredicate je způsob konstrukce podmínky NeXTSTEP pro filtrování kolekce (NSArray, NSSet, NSDictionary).

Zvažte například dvě pole arr a filteredarr:

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

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

filtrované položky jistě budou mít položky, které obsahují samotný znak c.

aby bylo snadné si vzpomenout na ty, kteří mají malé sql pozadí 

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

1) vyberte * z kolekce tbl ->

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

3) vyberte * z tbl, kde sloupec1 jako '% a%' ->

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

Doufám, že to pomůže 

3
Durai Amuthan.H

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

Tuto kategorii si můžete stáhnout zde

2
skywinder

Pokladna této knihovny

https://github.com/BadChoice/Collection

Dodává se se spoustou snadných funkcí pole, aby se nikdy nezapsat smyčku znovu

Takže můžete prostě udělat:

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

nebo

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

Nejlepší a nejjednodušší způsob je vytvořit tuto metodu a předat pole a hodnotu:

- (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;
}
0
jalmatari