2013-08-14 4 views
1

NSFetchRequest을 사용하여 Core Data 스토리지에서 데이터를 가져 와서 해당 데이터를 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]]; 

내가 두 번째 NSSortDescriptorNSComparator 블록이 호출되지 것입니다이 문제 (내가 NSLog에 시도). 내 데이터 구조에 몇 가지 배경을 제공하기 위해, 여기에 관련 Core Data 객체 그래프 섹션의 :

http://screencast.com/t/AOY6IdNFWoK

어떤 응용 프로그램이하는 것입니다 그것은 서로 항목을 비교합니다. 첫 번째 단계로 한 쌍의 비교에서 우승자는 score 증가합니다. 또한 우승자와 패자 사이에 일대일 lessImportantItems 관계를 추가합니다. 그래서 배열에서 먼저 score으로 정렬하려고 시도한 다음 score이 같을 때, 또한 쌍으로 된 우선 순위로 정렬하고 정렬합니다.

아마도 score을 비교기 key 두 번 연속 사용했기 때문일 수 있습니다. 그러나 다른 한편으로는 NSComparatorrelationshipkey으로 전달할 수 없습니다.

나는 이것을 왜곡 할 수 없습니다. 누구든지 아이디어가 있습니까? 아니면 정렬을 위해 다른 접근 방식을 취해야합니까?

+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을 반환하지 않습니다,
  • 들어 두 개의 "관련이없는 객체" 순서 ("비대칭"이 아님)와 관계없이 123을 반환합니다. item1이 간접적으로 만 item2 (아니 "과도").

"관련없는 개체"를 정렬하는 방법은 무엇입니까? 독특한 해결책은 없습니다. B와 C가 A보다 덜 중요한 이면 A, B, C와 A, C, B 모두 유효한 솔루션입니다. B와 C를 비교할 때 비교기가 반환해야하는 것은 무엇입니까?

그래서 정렬 정렬 자로는 성취 할 수 없으며 다른 알고리즘을 선택해야한다고 생각합니다. "Topological sorting".

+1

''대칭 '이 아닙니다' '비대칭이 아닙니다' ' – newacct

+0

@newacct : 죄송합니다 - 예 - 수정되었습니다. –

+0

감사합니다 마틴, 그 대답이 있습니다. 몇 가지 변경 사항을 소화하고 시험해 볼 시간이 필요합니다. – artooras

0

관심있는 사람이 있다면, 내가 어떻게 정렬했는지를 알 수 있습니다.

나는 위의 arrayscore으로 분류 얻을에만 예에서 첫 번째 NSSortDescriptor를 사용하고 그 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으로 끝납니다.

관련 문제