2012-11-21 4 views
17

클래스 Event가 있고 그것이 action (NSString) 및 date (NSDate)의 두 가지 속성이 있다고 가정합니다.해당 객체의 속성을 비교하여 배열에서 중복을 제거합니다.

그리고 이벤트 객체의 배열이 있다고 가정합니다. 문제는 "날짜"속성이 일치 할 수 있다는 것입니다.

중복을 제거해야합니다. 동일한 날짜의 2 개의 다른 객체가 중복됨을 의미합니다.

문자열이나 nsdates의 배열에서 중복을 제거 할 수 있으므로 비교하기 쉽습니다. 그러나 복잡한 물체를 어떻게 처리 할 것인가?

내가 지금까지 한 일을 묻지 마라. 내 마음에 오는 유일한 것은 버블 정렬이다. 하지만 초보자 용 솔루션이고 느리다..

매우 도움이되는 매우 큰 도움이됩니다 (링크, tuts, 코드).

미리 감사드립니다.

편집 dasblinkenlight에

덕분에, 나는 사용자 정의 방법을 만든 : 여기

- (NSArray *)removeDuplicatesInArray:(NSArray*)arrayToFilter{ 

    NSMutableSet *seenDates = [NSMutableSet set]; 
    NSPredicate *dupDatesPred = [NSPredicate predicateWithBlock: ^BOOL(id obj, NSDictionary *bind) { 
     YourClass *e = (YourClass*)obj; 
     BOOL seen = [seenDates containsObject:e.propertyName]; 
     if (!seen) { 
      [seenDates addObject:e.when]; 
     } 
     return !seen; 
    }]; 
    return [arrayToFilter filteredArrayUsingPredicate:dupDatesPred]; 
} 

YourClass 객체가 속한 클래스의 이름을, 그리고 propertyName은이다 당신이 비교하려고하는 객체의 속성.

self.arrayWithObjects에 YourClass의 개체가 있다고 가정합니다.

을 채우기 후,

self.arrayWithObjects = [self removeDuplicatesInArray:self.arrayWithObjects];

를 사용하면 모든 작업이 완료된다.

모든 크레딧은 dasblinkenlight입니다. 건배!

+0

어레이에있는 이벤트의 이벤트 객체를 다른 날짜와 함께 추가하는 것을 방지하기 위해 aproach를 사용하면 작동합니까? – LuisEspinoza

+0

Naah, 배열은 이미 거대한 JSON에서 채워집니다. 과정이 너무 복잡해서 나중에 중복을 제거하는 것이 더 쉽다고 생각합니다. –

+0

NSArray의 여러 sortedArray ... 함수 중 하나를 사용하여 날짜별로 배열을 정렬 한 다음 정렬 된 배열을 단계적으로 따라 가면서 새 NSMutableArray로 복사하고 마지막 NSArrayArray와 동일한 날짜를 갖는 모든 요소를 ​​건너 뜁니다. . –

답변

24

날짜의 NSMutableSet을 만들고 이벤트 목록을 반복하고 전에 만난 적이없는 날짜 만 이벤트를 추가 할 수 있습니다.

NSMutableSet *seenDates = [NSMutableSet set]; 
NSPredicate *dupDatesPred = [NSPredicate predicateWithBlock: ^BOOL(id obj, NSDictionary *bind) { 
    Event *e = (Event*)obj; 
    BOOL seen = [seenDates containsObject:e.date]; 
    if (!seen) { 
     [seenDates addObject:e.date]; 
    } 
    return !seen; 
}]; 
NSArray *events = ... // This is your array which needs to be filtered 
NSArray *filtered = [events filteredArrayUsingPredicate:dupDatesPred]; 
+0

효과가있었습니다. 쉽고 빠르게. 다시 한번 감사드립니다. –

3

kvc에서 작동하지 않습니까? 나는 다음과 같은 해결책이 당신의 경우에 효과가있을 것이라고 생각한다; 존재 여부를 O 인 경우

Event *event1 = [[Event alloc] init]; 
event1.name = @"Event1"; 
event1.date = [NSDate distantFuture]; 
Event *event2 = [[Event alloc] init]; 
event2.name = @"Event2"; 
event2.date = [NSDate distantPast]; 
Event *event3 = [[Event alloc] init]; 
event3.name = @"Event1"; 
event3.date = [NSDate distantPast]; 
NSArray *array = @[event1, event2, event3]; 

NSArray *filteredEvents = [array valueForKeyPath:@"@distinctUnionOfObjects.name"]; 
+1

'@ distinctUnionOfObjects.name'는 "name"이라는 고유 속성 속성의 배열 만 반환합니다. 나머지 개체는 아닙니다. – lagos

0

내가 가장 효과적인 방법은 값과 키와 속성 값으로 객체를 저장하는 NSDictionary를 사용하는 것입니다 생각하고, 사전에 어떤 객체를 추가하기 전에 당신은 (1 확인) 연산, 즉전체 프로세스는 O (n)이 여기에

코드

- (NSArray *)removeDuplicatesFromArray:(NSArray *)array onProperty:(NSString *)propertyName { 
    NSMutableDictionary *dictionary = [[NSMutableDictionary alloc] init]; 

    for (int i=0; i<array.count; i++) { 

     NSManagedObject *currentItem = array[i]; 
     NSString *propertyValue = [currentItem valueForKey:propertyName]; 

     if ([dictionary valueForKey:propertyValue] == nil) { 
      [dictionary setValue:currentItem forKey:propertyValue]; 
     } 
    } 

    NSArray *uniqueItems = [dictionary allValues]; 

    return uniqueItems; 
} 

다음

다음
self.arrayWithObjects = [self removeDuplicatesFromArray:self.arrayWithObjects onProperty:@"when"]; 
2
NSMutableArray *leftObjects = [duplicateArray mutableCopy]; 
NSMutableArray *nonDuplicates = [NSMutableArray new]; 
while (leftObjects.count > 0) 
{ 
    YourClass *object = [leftObjects objectAtIndex:0]; 

    // find all objects matching your comaprison equality definition for YourClass 
    NSArray *matches = [leftObjects filteredArrayUsingPredicate: 
         [NSPredicate predicateWithBlock:^BOOL(YourClass *evaluatedObject, NSDictionary *bindings) 
         { 
          return (evaluatedObject.name == object.name); 
         }] ]; 
    [leftObjects removeObjectsInArray:matches]; 

    // add first object (arbitrary, may decide which duplicate to pick) 
    [nonDuplicates addObject:matches.firstObject]; 
} 
0

로 사용할 수 있습니다 걸립니다은있는 NSArray 클래스에 신속한 확장 지정된 속성에 대해 중복을 제거하는 :

extension NSArray { 
/** 
- parameter property: the name of the property to check for duplicates 

- returns: an array of objects without objects that share an identical value of the specified property 
*/ 
    func arrayWithoutObjectsOfDuplicateProperty(property : String) -> [AnyObject] { 
    var seenInstances = NSMutableSet() 

    let predicate = NSPredicate { (obj, bind) -> Bool in 
     let seen = seenInstances.containsObject(obj.valueForKey(property)!) 

     if !seen { 
     seenInstances.addObject(obj.valueForKey(property)!) 
     } 
     return !seen 
     }  
     return self.filteredArrayUsingPredicate(predicate) 
    } 
} 
0

여기에서 작동합니다. 은 요소의 순서를 유지하면서 중복을 제거합니다..

// Custom Struct. Can be also class. 
// Need to be `equitable` in order to use `contains` method below 
struct CustomStruct : Equatable { 
     let name: String 
     let lastName : String 
    } 

// conform to Equatable protocol. feel free to change the logic of "equality" 
func ==(lhs: CustomStruct, rhs: CustomStruct) -> Bool { 
    return (lhs.name == rhs.name && lhs.lastName == rhs.lastName) 
} 

let categories = [CustomStruct(name: "name1", lastName: "lastName1"), 
        CustomStruct(name: "name2", lastName: "lastName1"), 
        CustomStruct(name: "name1", lastName: "lastName1")] 
print(categories.count) // prints 3 

// remove duplicates (and keep initial order of elements) 
let uniq1 : [CustomStruct] = categories.reduce([]) { $0.contains($1) ? $0 : $0 + [$1] } 
print(uniq1.count) // prints 2 - third element has removed 

그리고 단지의 경우

당신이 마법의 작품을 줄이는 방법을 궁금해 - 동일 여기 만 사용하여 더 많은 당신은 단순히 스위프트 놀이터에이 코드를 복사하여 붙여 넣을 수 있습니다

let uniq2 : [CustomStruct] = categories.reduce([]) { (result, category) in 
    var newResult = result 
    if (newResult.contains(category)) {} 
    else { 
    newResult.append(category) 
    } 
    return newResult 
} 
uniq2.count // prints 2 - third element has removed 

구문을 줄이기 확대 주위에 놀아 라.

관련 문제