2012-11-21 71 views
17

假設我有一個類Event,它有兩個屬性:action(NSString)和date(NSDate)。從數組中刪除重複項,比較其對象的屬性

並假設我有一個Event對象的數組。問題是「日期」屬性可以匹配。

我需要刪除重複項,這意味着2個不同的對象具有相同的日期是重複的。

我可以刪除任何字符串或nsdates數組中的重複項,它們很容易比較。但是如何用複雜的對象來完成它們的屬性比較呢?

不要問我到目前爲止我做了什麼,因爲我唯一想到的就是冒泡,,但這是一個新手解決方案,並且很慢

非常感謝任何幫助(鏈接,內容,代碼)。

在此先感謝。

編輯

感謝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

如果採取措施避免添加日期等於另一個事件對象的事件已經存在於數組中? – LuisEspinoza

+0

Naah,該數組已經從巨大的JSON中填充。這個過程太複雜了,我認爲之後刪除重複項更容易。 –

+0

按日期對數組進行排序(這很容易使用NSArray的幾個sortedArray ...函數之一),然後遍歷排序後的數組,複製到新的NSMutableArray,跳過與最後一個日期相同的任何元素。 –

回答

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。我想下面的解決方案可以在你的情況下工作;

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存儲對象值和屬性值作爲重點,並添加任何對象字典,然後檢查是否存在與否是O(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 

您可以簡單地將此代碼複製粘貼到一個斯威夫特遊樂場並玩耍。

相關問題