Предикат NSP, который может рекурсивно пройти по графу объектов? - PullRequest
3 голосов
/ 18 февраля 2010

Я пытаюсь отфильтровать массив объектов, которые по существу формируют граф в виде дерева.что я хочу сделать, это отфильтровать все объекты из этого массива, у которых свойство visible имеет значение NO, или если его свойство visible родительского / дедушки / и т. д. имеет значение true (дочерние объекты могут иметь свойство visible, равное YES, тогда как его родитель может иметь значение NO).

Мне неясно, как бы я поступил так, используя синтаксис NSPredicate, чтобы продолжать поиск родительского узла, пока нет родителей или не будет найдено видимое свойство.Есть ли способ пойти по этому поводу?

Ответы [ 2 ]

1 голос
/ 13 марта 2012

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

  • Пусть метод свойства visible ведет себя рекурсивно, вместо того чтобы делать это предикатом формата.Это может быть выполнено следующим образом:
- (BOOL) isVisible {
  return visible && [parent isVisible];
}

//...
id filtered = [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"visible == YES"]];
  • Использовать блочные предикаты вместо форматных предикатов для рекурсивного обхода:
[array filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {

    id obj = evaluatedObject;
    while (obj) {
      if (![obj isVisible]) return NO;
      obj = [obj parent];
    }
    return YES;
}]];

Или их комбинация (которая, на мой взгляд, была бы наиболее надежной и удобочитаемой).

0 голосов
/ 02 декабря 2010

Я не уверен, что то, что вы хотите сделать, возможно с помощью простого единственного предиката.Если это дерево и вы используете предикат для получения узлов, вам нужно и написать метод, который будет проходить вверх и возвращать BOOL, указывающий, следует ли его удалить или нет.

Затем простополучите ваши узлы и поместите их в NSMutableArray и выполните

for (int i = 0; i < [results count]; i++)
{
    if ([self shouldBeRemoved:[results objectAtIndex:i]])
    {
        [results removeObjectAtIndex:i];
        i--;
    }
}

Ваш shouldBeRemoved: метод должен быть довольно простым рекурсивным методом.

...