Objective-C: перебрать массив объектов и удалить объекты, которые соответствуют значению в другом массиве

У меня есть 2 массива, один содержит набор идентификаторов, а другой - набор объектов (аналогично приведенному ниже):

NSArray *identifierArray = @[@100, @200, @300];
NSArray *peopleArray = @[@{@"id": @100, @"name": @"Ben"}, @{@"id": @200, @"name": @"Alex"}, @{@"id": @300, @"name": @"Sarah"}, @{@"id": @400,@"name": @"George"}, @{@"id": @500, @"name": @"Jessica"}];

Я хочу иметь возможность прокручивать peopleArray и проверять, есть ли у какого-либо из объектов идентификатор, который отображается в identifierArray. Если совпадение найдено, он должен удалить объект из identifierArray, что приведет к:

NSArray *peopleArray = @[@{@"id": @400,@"name": @"George"}, @{@"id": @500, @"name": @"Jessica"}];

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

    for (NSNumber *id in activePeople) {
        for (int i = 0; i < peopleArray.count; i++) {
            if (id == [peopleArray[i] valueForKey:@"id"]) {
                NSLog(@"Should remove...%@")
            }
        }
    }

Может ли кто-нибудь указать мне, как я могу это сделать?

Я голосую за то, чтобы закрыть этот вопрос как не по теме, потому что это домашнее задание

Cy-4AH 13.09.2018 10:35
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
172
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Скорее всего, вы не сможете использовать == для сравнения двух объектов в этом случае, а вместо этого используйте isEqual:

== сравнивает значения указателей. В вашем случае кажется, что они не будут такими же.

isEqual: вместо этого сравнивает сами объекты.

Чтобы повторно использовать свой код, вы можете попробовать следующее:

for (NSNumber *id in activePeople) {
    for (int i = 0; i < peopleArray.count; i++) {
        if ([id isEqual:[peopleArray[i] valueForKey:@"id"]) {
            NSLog(@"Should remove...%@")
        }
    }
}

Только что попробовал, но, похоже, не удаляет объект (/ NSLog не выводит на консоль)?

Jason 12.09.2018 22:54
Ответ принят как подходящий

Я предлагаю отказаться от циклов и использовать более современный блочный API indexesOfObjectsPassingTest (который фактически существует с 2009 года в macOS 10.6 Snow Leopard и iOS 4.0).

NSArray *identifierArray = @[@100, @200, @300];
NSMutableArray *array = [@[@{@"id": @100, @"name": @"Ben"}, @{@"id": @200, @"name": @"Alex"}, @{@"id": @300, @"name": @"Sarah"}, @{@"id": @400,@"name": @"George"}, @{@"id": @500, @"name": @"Jessica"}] mutableCopy];
NSIndexSet *indexes = [array indexesOfObjectsPassingTest:^BOOL(NSDictionary *obj, NSUInteger idx, BOOL *stop) {
    return [identifierArray containsObject:obj[@"id"]];
}];
[array removeObjectsAtIndexes:indexes];
NSLog(@"%@", array);

Или еще более эффективная фильтрация массива с помощью предиката (доступно начиная с macOS 10.4 Tiger и iOS 3.0 в 2005 году (!))

NSArray *identifierArray = @[@100, @200, @300];
NSArray *array = @[@{@"id": @100, @"name": @"Ben"}, @{@"id": @200, @"name": @"Alex"}, @{@"id": @300, @"name": @"Sarah"}, @{@"id": @400,@"name": @"George"}, @{@"id": @500, @"name": @"Jessica"}];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT id IN %@", identifierArray];
NSArray *result = [array filteredArrayUsingPredicate:predicate];
NSLog(@"%@", result);

Если значения id должны быть строками, замените все вхождения @x00 на @"x00".

Учитывая оба попытки, но оба, похоже, не удаляют объекты с идентификаторами 100, 200 или 300. Я, должно быть, что-то упускаю ...

Jason 12.09.2018 23:02

Оба фрагмента должны работать автономно. Идентификаторы действительно объекты NSNumber?

vadian 12.09.2018 23:06

А, думаю, я мог решить эту проблему, используя приведенный вами пример предиката, просто заменив predicateWithFormat:@"NOT id IN %@", identifierArray] на predicateWithFormat:@"id == %@", identifierArray]. Если вы сможете обновить свой ответ, я с радостью приму, надеюсь, поможет кому-то еще в будущем. Цените помощь!

Jason 12.09.2018 23:08

Если вы хотите использовать хранить 400 и 500, как описано в вопросе, код правильный, @"id == %@", identifierArray не может работать.

vadian 12.09.2018 23:10

Ах, как вы это упомянули, я только что напечатал тип данных id в array в примере, и на самом деле это NSTaggedPointerString, а id в identifierArray - это __NSCFNumber, поэтому, должно быть, у меня это не сработало.

Jason 12.09.2018 23:13

Работает отлично, моя вина ... соответствует двум типам данных и работает должным образом. Спасибо!

Jason 12.09.2018 23:20

Другие вопросы по теме