фильтрация NSArray в новый NSArray в target-c

У меня есть NSArray, и я хочу создать новый NSArray с объектами из исходного массива, которые соответствуют определенным критериям. Критерии определяются функцией, которая возвращает BOOL.

Я могу создать NSMutableArray, перебрать исходный массив и скопировать объекты, которые принимает функция фильтра, а затем создать неизменяемый версия этого.

Есть ли лучший способ?

108 голосов | спросил lajos 21 stEurope/Moscowp30Europe/Moscow09bEurope/MoscowSun, 21 Sep 2008 09:36:29 +0400 2008, 09:36:29

8 ответов


0

NSArray и NSMutableArray предоставляют методы фильтровать содержимое массива. NSArray предоставляет FilterArrayUsingPredicate: , который возвращает новый массив, содержащий объекты в приемнике, которые соответствуют указанному предикату. NSMutableArray добавляет filterUsingPredicate: , который оценивает содержимое получателя по указанному предикату и оставляет только совпадающие объекты. Эти методы иллюстрируются в следующем примере.

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" }
ответил lajos 21 stEurope/Moscowp30Europe/Moscow09bEurope/MoscowSun, 21 Sep 2008 09:43:47 +0400 2008, 09:43:47
0

Есть множество способов сделать это, но самым лучшим из них, безусловно, является использование [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.
}]];

Я думаю, что это настолько кратко, насколько это возможно.


Swift:

Для тех, кто работает с NSArray в Swift, вы можете предпочесть эту еще более краткую версию:

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

filter - это просто метод для Array (NSArray неявно соединен с Array

ответил Stuart 22 +04002013-10-22T16:06:55+04:00312013bEurope/MoscowTue, 22 Oct 2013 16:06:55 +0400 2013, 16:06:55
0

Если вы используете OS X 10.6 /iOS 4.0 или более позднюю версию, вам лучше использовать блоки, чем NSPredicate. См. -[NSArray indexesOfObjectsPassingTest:] или напишите свою собственную категорию, чтобы добавить удобный -select: или метод -filter: ( пример ).

Хотите, чтобы кто-нибудь еще написал эту категорию, протестировал ее и т. д.? Ознакомьтесь с BlocksKit ( документы массива ). И есть много других примеров, например, при поиске, например, " выбор категории блоков nsarray ".

ответил Clay Bridges 4 +04002010-10-04T20:22:44+04:00312010bEurope/MoscowMon, 04 Oct 2010 20:22:44 +0400 2010, 20:22:44
0

На основе ответа от Clay Bridges приведен пример фильтрации с использованием блоков (замените yourArray на имя переменной массива и ---- +: = 1 =: + ---- к названию вашей функции тестирования):

testFunc
ответил pckill 8 42012vEurope/Moscow11bEurope/MoscowThu, 08 Nov 2012 16:14:23 +0400 2012, 16:14:23
0

NSPredicate - это способ построения условия nextstep для фильтрации коллекции (NSArray, NSSet, NSDictionary).

Например, рассмотрим два массива: arr и filteredarr

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

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

в фильтрующем элементе обязательно будут элементы, содержащие только символ c.

чтобы было легче вспомнить тех, у кого мало sql фона, это

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

1) выберите * из таблицы -> Коллекция

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

3) выберите * из таблицы, где столбец1 похож на "% a%" ->

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

Надеюсь, это поможет

ответил Durai Amuthan.H 4 PMpThu, 04 Apr 2013 14:51:50 +040051Thursday 2013, 14:51:50
0

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

Вы можете скачать эту категорию здесь

ответил skywinder 16 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowTue, 16 Sep 2014 12:25:12 +0400 2014, 12:25:12
0

Оформить заказ этой библиотеки

https://github.com/BadChoice/Collection

Он поставляется с множеством простых функций массива, которые больше никогда не пишут цикл.

Так что вы можете просто сделать:

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

или

NSArray* oldHeroes = [self.heroes reject:^BOOL(Hero *object) {
    return object.age.intValue < 20;
}];
ответил Jordi Puigdellívol 29 PM00000080000000331 2016, 20:56:03
0

Лучший и простой способ - создать этот метод и передать массив и значение.

- (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;
}
ответил jalmatari 20 22018vEurope/Moscow11bEurope/MoscowTue, 20 Nov 2018 04:39:36 +0300 2018, 04:39:36

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132