2013-08-14 2 views
1

Я получаю данные от Core Data хранения с использованием NSFetchRequest и храните эти данные в array - все отлично работает. В качестве следующего шага, я хочу разобраться, что array используя NSSortDescriptors так:Блок NSComparator не называется

array = [array sortedArrayUsingDescriptors:[NSArray arrayWithObjects: 
      [NSSortDescriptor sortDescriptorWithKey:@"score" ascending:NO], 
      [NSSortDescriptor sortDescriptorWithKey:@"score" ascending:NO comparator:^NSComparisonResult(id obj1, id obj2) { 
        if ([[[array objectAtIndex:[obj2 integerValue]] valueForKey:@"lessImportantItems"] containsObject:[array objectAtIndex:[obj1 integerValue]]]) { 
         return (NSComparisonResult)NSOrderedAscending; 
        } else { 
         return (NSComparisonResult)NSOrderedDescending; 
        } 
       }], 
      [NSSortDescriptor sortDescriptorWithKey:@"createdAt" ascending:NO], nil]]; 

У меня есть проблема в том, что NSComparator блок во втором NSSortDescriptor не называется (я пытался NSLog). Чтобы дать некоторый фон для моей структуры данных, вот соответствующий Core Data объектный граф раздела:

http://screencast.com/t/AOY6IdNFWoK

Что приложение делает это сравнивает элементы друг с другом. В качестве первого шага победитель в парном сравнении получает приращение score. Но также я отмечаю спаренный приоритет, т. Е. Добавляю отношение «один ко многим» lessImportantItems от победителя к проигравшему. Итак, в моем массиве я сначала пытаюсь сортировать по score, а затем, когда score s равны, я также пытаюсь сортировать по парному приоритету.

Возможно, это потому, что я использую score в качестве компаратора key два раза подряд? Но, с другой стороны, NSComparator не позволяет передавать relationship как key.

Я, похоже, не могу взломать этот. У кого-нибудь есть идеи? Или, может быть, я должен придерживаться другого подхода к сортировке?

+0

Итак, конечный результат, который вы хотите, - это сортировка предметов? В любом методе? Или ваш вариант? – geekchic

+0

Ну, это как он говорит с дескрипторами сортировки: (1) сортировать по счету, затем (2), если оценка равна, сортировать по более важному один на один и, наконец, (3) сортировать по дате, созданной (реалистично будет для элементов в хвосте, то есть те, которые имеют одинаковую оценку 0 - еще не сравнили). Это то, о чем вы спрашивали? – artooras

ответ

1

Второй дескриптор сортировки не имеет для меня никакого смысла. Он применяет данный компаратор к атрибуту score сравниваемых объектов. Таким образом, внутри компаратора obj1, obj2 - это значения очков для сравниваемых объектов. кажется, что вы пытаетесь получить основные объекты с

[array objectAtIndex:[obj1 integerValue]] 
[array objectAtIndex:[obj2 integerValue]] 

, но это не может работать. Таким образом, второй дескриптор сортировки должен выглядеть

[NSSortDescriptor sortDescriptorWithKey:@"self" ascending:NO 
     comparator:^NSComparisonResult(Item *item1, Item *item2) { 

     // compare item1, item2 ... 
}]; 

Но тогда возникает следующая проблема: Как сравнить два объекта в соответствии с приоритетом? Ваш код делает по существу следующее:

if ([item2 valueForKey:@"lessImportantItems"] containsObject:item1]) { 
    return NSOrderedAscending; 
} else { 
    return NSOrderedDescending; 
} 

Но это не является надлежащим компаратором:

  • Он не возвращается NSOrderedSame, если объекты равны (не «рефлексивный»),
  • Для два «несвязанных объекта» он вернет NSOrderedDescending независимо от (не «асимметричный»),
  • он не обнаруживает, что item1 косвенно ссылается ed до item2 (не «переходный»).

Но как сортировать "несвязанные объекты"? Не существует уникального решения. Если оба B и C равны , менее важным, чем A, то как A, B, C, так и A, C, B являются действительными решениями. Что должен возвращать компаратор при сравнении B и C?

Поэтому я думаю, что этого не может быть достигнуто с помощью дескриптора сортировки и вам нужно выбрать какой-либо другой алгоритм, например. "Topological sorting".

+1

«не« симметричный »« вы имеете в виду «не» асимметричный » – newacct

+0

@newacct: Упс - да - исправлено. –

+0

Спасибо, Мартин, это какой-то ответ. Мне нужно некоторое время, чтобы переварить и попробовать некоторые изменения. – artooras

0

Если кому-то интересно, вот как я добился сортировки, которой я был.

я использовал только первый NSSortDescriptor из приведенного выше примера, чтобы получить array отсортированы по score, а затем я назвал метод дальнейшей сортировки по этому array:

array = [array sortedArrayUsingDescriptors:[NSArray arrayWithObjects: 
      [NSSortDescriptor sortDescriptorWithKey:@"score" ascending:NO], nil]; 

array = [self applyMoreImportantPairOrdering:array]; 

А вот метод:

+ (NSArray *)applyMoreImportantPairOrdering:(NSArray *)array { 

    NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:array]; 

    [array enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 

     if ([[obj valueForKey:@"score"] integerValue] > 0) { 

      NSMutableSet *lessImportantItemsSet = [NSMutableSet setWithSet:[obj valueForKey:@"lessImportantItems"]]; 

      for (int i = idx - 1; i >= 0; i--) { 

       NSManagedObject *objAbove = [array objectAtIndex:i]; 

       if ([[obj valueForKey:@"score"] integerValue] == [[objAbove valueForKey:@"score"] integerValue]) { 

        if ([lessImportantItemsSet containsObject:objAbove]) { 

         NSUInteger idxAbove = [mutableArray indexOfObject:objAbove]; 

         [mutableArray removeObject:obj]; 
         [mutableArray insertObject:obj atIndex:idxAbove]; 
        } 
       } 
      } 
     } 
    }]; 

    return [NSArray arrayWithArray:mutableArray]; 
} 

Причина, по которой мне нужен lessImportantItemsSet, заключается в том, что когда я перемещаю (удаляю и вставляю) item в array, он теряет его отношения lessImportantItems. Этот способ я поддерживаю список/набор менее важных item s, пока я закончил с конкретным item.

Смежные вопросы