2012-11-21 19 views
17

Bir sınıf Etkinliğimiz olduğunu ve 2 özelliğe sahip olduğunu varsayalım: action (NSString) ve date (NSDate).Nesnelerinin özelliklerini karşılaştıran diziden kopyaları kaldırın

Ve bir dizi Olay nesnem var. Sorun, "tarih" özelliklerinin eşleşmesidir.

Yinelenen kopyaları çıkarmam gerekiyor, yani aynı tarih olan 2 farklı nesne çoğaltıyor.

Yinelenen dizeleri veya nsdates dizilerinden kaldırabilirim, karşılaştırmaları kolaydır. Ama özellikleri karşılaştırılacak karmaşık nesnelerle nasıl yapılır?

Şimdiye kadar ne yaptığımı sorma, çünkü aklıma gelen tek şey bir kabarcık sıralaması, , ama bir acemi çözümü ve yavaş.

Her türlü yardım son derece takdir edilir (bağlantılar, tuts, kod).

Şimdiden teşekkürler.

DÜZENLEME dasblinkenlight için

teşekkürler, ben özel bir yöntem yaptık: Burada

- (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 nesne aittir sınıfın adıdır ve propertyName olduğunu karşılaştırmak istediğiniz nesnenin mülkiyeti.

Self.arrayWithObjects öğesinin, YourClass öğesinin nesnelerini içerdiğini varsayalım.

onu doldurma sonra

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

kullanmak ve bitirdiniz.

Tüm krediler dasblinkenlight. Şerefe!

+0

Dizide zaten bulunan Olaylar'dan başka biriyle eşit olay nesnelerini eklemeyi engellemek için öneriyi kullanırsanız çalışır? – LuisEspinoza

+0

Naah, dizi zaten büyük bir JSON'dan dolduruluyor. İşlem çok karmaşık, sonra kopyaları kaldırmak daha kolay olduğunu düşünüyorum. –

+0

Diziyi tarihe göre sıralayın (NSArray öğesinin birkaç sıralanmışArray ... işlevinden birini kullanarak oldukça kolaydır), ardından sıralanmış diziye adım atın, yeni bir NSMutableArray öğesine kopyalayın, sonuncu tarihle aynı tarihe sahip herhangi bir öğeyi atlayın . –

cevap

24

Bir NSMutableSet tarihini oluşturabilir, etkinlik listenizi yineleyebilir ve yalnızca daha önce karşılaşmadığınız bir tarihi ekleyebilirsiniz.

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

Çalıştı. Kolay, hızlı. Tekrar teşekkürler. –

3

Bu, kvc ile çalışmadı. Sanırım aşağıdaki çözüm sizin durumunuzda işe yarayabilir; o yok veya O olduğu takdirde

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 'yalnızca" name "adında bir benzersiz özellik dizisi döndürür. Nesnelerin geri kalanı değil. – lagos

0

Ben en etkili yolu değeri ve anahtar olarak mülkiyet değeri olarak nesneyi saklamak için NSDictionary kullanmak olduğunu düşünüyorum ve sözlüğe herhangi bir nesne eklemeden önce (1 çek) operasyon, yaniTüm süreç O (n) İşte

kod

- (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; 
} 

aşağıdaki

İşte
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

olarak kullanabilirsiniz olduğunu alacaktır NSArray sınıfına bir Swift uzantısıdır Belirtilen özellik için yinelenen kaldırır:

0

Burada, çalışma kodu öğelerinin sırasını korurken, kopyaları yapan yinelenen silinen Swift kodu çalışıyor.

// 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 

Ve eğer

Bunu sihirli eserler azaltmak nasıl olacağını merak - tamamen aynı burada ama kullanarak daha fazla Sadece bir Swift Oyun bu kodu kopyalayıp yapıştırın

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 

sözdizimini azaltmak genişletilmiş ve etrafta oynayın.

İlgili konular