2014-03-06 2 views
1

매우 구체적인 방식으로 필터링해야하는 사전이 있습니다. 예를 들어 설명하는 것이 가장 쉽습니다.NSArray의 사전 객체 비교를 통한 필터링

NSDictionary #1: 
@"threadId" : @"1234" 
@"subject" : @"hello" 
@"messageId" : @"0001" 

NSDictionary #2: 
@"threadId" : @"1234" 
@"subject" : @"hello" 
@"messageId" : @"0002" 

NSDictionary #3: 
@"threadId" : @"9101" 
@"subject" : @"goodbye" 
@"messageId" : @"0005" 

나는 같은이있는 사전을 고려 중이 야 :

의 나는 다음과 같은 세 가지 사전을 포함한 배열이 있다고 가정 해 봅시다 @ "대상"@ "threadId을", "messageId가"@ 열쇠 @ "threadId"와 @ "subject"에 대한 값은 @ "messageId"가 다른 경우에도 마찬가지입니다. 따라서 사전 1과 사전 2를 중복으로 생각하고 위의 배열에서 사전 1 또는 사전 2 중 하나 (둘 다 아님)를 제거하고 싶습니다. 즉, 사전 3 개 또는 사전 3 개 또는 사전 2와 3을 모두 포함하는 새로운 배열로 세 사전의 원래 배열을 필터링하고 싶습니다.

지금까지 시도한 모든 시도로 인해 과도한 결과가 발생했습니다 for 루프는 threadId로 사전을 정렬하고 분리하려고 시도하지만, 비교 부분에서 멈추게됩니다. 나는 술어에 의한 필터링을 살펴 봤지만 다른 객체와의 비교와는 아무런 관련이없는 특정 기준을 만족하는 객체 만 제거하는 것처럼 보입니다. 중복 될 것으로 생각되는 객체가 실제로 중복되지 않기 때문에 NSSet이 작동하지 않습니다.

누구든지이 필터링을 수행하기위한 일반적인 전략을 제안 할 수 있는지 궁금합니다.

+0

가능한 복제본 : http://stackoverflow.com/a/13499453/1301013 데이터 집합을 조작 할 때 NSPredicate를 사용할 수 있습니다. –

답변

0

이 코드 순서 고유성 복합 키를 확인하기위한 MutableSet와 사전 먼저 체크 후 그 반복하는 경우 또는 전혀

NSSortDescriptor *sortDescriptor; 
//Order by threadId 
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"threadId" 
               ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)]; 

NSArray *arrayOrdered = [yourArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]]; 
NSMutableArray *arrayResult = [NSMutableArray array]; 
NSString* thread = nil; 
NSString* subj = nil; 
for (NSDictionary*dic in arrayOrdered) { 

    if ([thread length] == 0 && [subj length] == 0) { 
     thread = [dic objectForKey:@"threadId"]; 
     subj = [dic objectForKey:@"subject"]; 
    }else{ 

     if ([thread isEqualToString:[dic objectForKey:@"threadId"]]) { 
      if (![subj isEqualToString:[dic objectForKey:@"subject"]]) { 
       //We save it 
       [arrayResult addObject:dic]; 
      }else{ 
       //It´s already kept 
       NSLog(@"repeated dic"); 
      } 
     }else{ 
      [arrayResult addObject:dic]; 
     } 
    } 
} 
+0

감사합니다. 각 반복마다 thread와 subj를 nil로 재설정해야했습니다. 훌륭하게 작동합니다. – jac300

0

외부 루프가 모든 요소 (마지막 요소 제외)를 반복하고 내부 루프가 현재 위치에서 끝까지 모든 요소를 ​​반복하는 중첩 for 루프를 사용하여 수행 할 수 있습니다. 동일한 쌍을 찾으면 내부 루프의 값을 NSMutableSet에 추가 할 수 있습니다. 작업이 끝나면 배열에서 NSMutableSet의 모든 요소를 ​​제거하기 만하면됩니다. 이 작업을 수행하는 나의 시도

0

모든 지금까지 내가 threadId에 의해 별도의 사전을 정렬하고 시도하는 루프, 과도한 초래했다.

저는 이것이 전략 일 것이라고 생각합니다. 그래서 당신은 올바른 길을 가고있었습니다.

의사 코드 (구문에 신경 쓰지 마십시오)에서이 작업을 수행합니다. 당신이이 ennumerated되는 동안 배열에서 개체를 제거 할 수 없습니다 때문에 제거에 대한

String *threadid, *subject; 
// Important: Array must be already sorted (e.g. with a sortDescriptor) 
for (NSDictionary *dict in Array) 
{ 
    if (threadid == dict.threadid && subject == dict.subject) 
    { 
      // mark for removal 
    } 
    threadid = dict.threadid; 
    subject = dict.subject; 
} 

마르크는, 새로운 배열을 제거 할 항목을 추가하는 것을 의미한다.

+0

이 코드는 먼저 정렬 된 경우에만 작동한다고 생각합니다. 그리고 대답은 이미 분류되어 있다고 말하지 않습니다. – Gavin

+0

@Gavin 그래서 '정렬'에 대한 사용자 의견을 붙여 넣었지만 동의합니다. 답을 수정하겠습니다. 감사! – Merlevede

0

이 작동합니다 :

NSArray *array = ...; // Your array of dictionaries 

// This is going to be the filtered array: 
NSMutableArray *unique = [NSMutableArray array]; 

// Set to keep track of all threadId/subject combinations added so far: 
NSMutableSet *set = [NSMutableSet set]; 

for (NSDictionary *d in array) { 
    // Create "sub-dictionary" that contains only the key/value pairs 
    // for determining uniqueness: 
    NSDictionary *tmp = [d dictionaryWithValuesForKeys:@[@"threadId", @"subject"]]; 
    // If we have don't have that combination already ... 
    if (![set containsObject:tmp]) { 
     // ... add the full dictionary to the new array ... 
     [unique addObject:d]; 
     // ... and the threadId/subject combination to the set. 
     [set addObject:tmp]; 
    } 
} 
0

간단한 루프.

NSMutableArray *filteredArray = [[NSMutableArray alloc] initWithCapacity:messages.count]; 
NSMutableSet *keysSet = [[NSMutableSet alloc] init]; 

for (NSDictionary *msg in messages) { 
    NSString *key = [NSString stringWithFormat:@"%@%@", msg[@"threadId"], msg[@"subject"]]; 
    if (![keysSet containsObject:key]) { 
     [filteredArray addObject:msg]; 
     [keysSet addObject:key]; 
    } 
}