2017-08-14 60 views
0

我有一個具有多個屬性的自定義對象。在多個屬性上排列NSArray自定義對象

一個屬性是一個類型,例如枚舉:A,B,C等

這些都有一個日期太。

@property (assign) CustomType customType; 
@property (nonatomic, strong) NSDate *startDate; 
... 

typedef NS_ENUM(NSInteger, CustomType) { 
    A, 
    B, 
    C 
}; 

我想提出類型的所有對象「C」,然後先通過訂購的日期降序休息。

達到此目的的最佳方法是什麼?

我試着添加多個sortDescriptors,但我只想C頂部的對象,然後按日期排序的其餘部分,這將按日期排序每個分組。

NSSortDescriptor *sortDescriptor1 =[[NSSortDescriptor alloc] initWithKey:@"customType" ascending:NO]; 
NSSortDescriptor *sortDescriptor2 =[[NSSortDescriptor alloc] initWithKey:@"startDate" ascending:NO]; 
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, sortDescriptor2, nil]; 
NSArray *sortedObjects = [_items sortedArrayUsingDescriptors:sortDescriptors]; 

+-------------------------+ 
| C | 2017-08-16 12:48:53 | 
| C | 2017-08-15 12:46:53 | 
| B | 2017-08-16 12:48:53 | 
| B | 2017-08-14 12:43:53 | 
| A | 2017-08-15 12:46:53 | 
| A | 2017-08-14 12:31:53 | 
+-------------------------+ 

+-------------------------+ 
| C | 2017-08-16 12:48:53 | 
| C | 2017-08-15 12:46:53 | 
| A | 2017-08-16 12:48:53 | 
| B | 2017-08-15 12:46:53 | 
| A | 2017-08-14 12:43:53 | 
| B | 2017-08-14 12:31:53 | 
+-------------------------+ 

而且我能決定,我想這customType第一,所以我可能會想B到在頂部,然後剛剛休息按日期?


將數組拆分成兩組,然後是其餘所有組,將數組拆分成兩組會更容易。對每個子組進行排序,然後將它們一起加入?

然後我可以選擇我想在下面的謂語其中最高組:

NSPredicate *pred1 = [NSPredicate predicateWithFormat:@"customType == %ld", C]; 
NSPredicate *pred2 = [NSPredicate predicateWithFormat:@"customType != %ld", C]; 
NSArray *top = [_items filteredArrayUsingPredicate:pred1]; 
NSArray *bottom = [_items filteredArrayUsingPredicate:pred2]; 

NSSortDescriptor *sortDescriptor1 = [[NSSortDescriptor alloc] initWithKey:@"startDate" ascending:NO]; 
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor1, nil]; 
NSArray *sortedTop = [top sortedArrayUsingDescriptors:sortDescriptors]; 
NSArray *sortedBottom = [bottom sortedArrayUsingDescriptors:sortDescriptors]; 

//NSArray *items = [NSArray arrayWithObjects:sortedTop, sortedBottom, nil]; 

NSArray *newArray = @[]; 
newArray = [newArray arrayByAddingObjectsFromArray:sortedTop]; 
newArray = [newArray arrayByAddingObjectsFromArray:sortedBottom]; 

_items = [newArray mutableCopy]; 

按日期排序 https://stackoverflow.com/a/6084944/2895831

NSLog(@"nodeEventArray == %@", nodeEventArray); 
NSSortDescriptor *dateDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"startDate" ascending:NO]; 
NSArray *sortDescriptors = [NSArray arrayWithObject:dateDescriptor]; 
NSArray *sortedEventArray = [nodeEventArray sortedArrayUsingDescriptors:sortDescriptors]; 
NSLog(@"sortedEventArray == %@", sortedEventArray); 

在過去,我已經分組一個給定屬性的數組,並在該單個屬性上使用自定義排序。

How to use Custom ordering on NSArray

@property (nonatomic, strong) NSString *level; 

NSArray *levels = [array valueForKeyPath:@"@distinctUnionOfObjects.level"]; 

NSArray *levelsSortOrder = @[@"Beginner", @"Basic", @"Intermediate", @"Expert", @"Advanced", @"Developer", @"Seminar"]; 

NSArray *sortedArray = [levels sortedArrayUsingComparator: ^(id obj1, id obj2){ 
    NSUInteger index1 = [levelsSortOrder indexOfObject: obj1]; 
    NSUInteger index2 = [levelsSortOrder indexOfObject: obj2]; 
    NSComparisonResult ret = NSOrderedSame; 
    if (index1 < index2) 
    { 
     ret = NSOrderedAscending; 
    } 
    else if (index1 > index2) 
    { 
     ret = NSOrderedDescending; 
    } 
    return ret; 
}]; 

回答

1

我喜歡sortedArrayUsingComparator:,我不認爲你可以做你想做和別人的方法是什麼。

sortedArrayUsingComparator:給出瞭如何排序真的很大的行動。 它背後的邏輯是: 比較它們之間的兩個對象(obj1obj2)。 你決定在這兩個排序。 它會遍歷整個數組,並通過比較每個對象兩個兩個它將有排序的結果。 因此,在塊中,您必須清楚地明確爲什麼定義對象是爲了優先於另一個對象。 這裏CustomType就是其中之一,並且在startDate之前優先。所以讓我們按照這個順序來做。

的再執行:

NSArray *sortedArray = [unsortedArray sortedArrayUsingComparator: ^(CustomClass *obj1, CustomClass2 *obj2){ 
    CustomType type1 = [obj1 customType]; 
    CustomType type2 = [obj2 customType]; 
    if (type1 == C && type2 == C) 
    { 
     return [[obj1 startDate] compare:[obj2 startDate]]; 
    } 
    else if (type1 == C && type2 != C) 
    { 
     return NSOrderedAscending; 
    } 
    else if (type1 != C && type2 == C) 
    { 
     return NSOrderedDescending; 
    } 
    else //if (type1 != C && type2 != C) 
    { 
     return [[obj1 startDate] compare:[obj2 startDate]]; 
    } 
}]; 

隨着一點點的重構(refactorization):

NSArray *sortedArray = [unsortedArray sortedArrayUsingComparator: ^(CustomClass *obj1, CustomClass2 *obj2){ 
    CustomType type1 = [obj1 customType]; 
    CustomType type2 = [obj2 customType]; 
    if (type1 == C && type2 != C) 
    { 
     return NSOrderedAscending; 
    } 
    else if (type1 != C && type2 == C) 
    { 
     return NSOrderedDescending; 
    } 
    else //Either (type1 == C && type2 == C) OR (type1 != C && type2 != C) 
    { 
     //return [[obj1 startDate] compare:[obj2 startDate]]; 
     return [[obj2 startDate] compare:[obj1 startDate]]; 
    } 
}]; 

注意NSOrderedAscendingNSOrderedDescending可能被逆轉,我從來不知道該用哪一個,我總是測試。

我用CustomClass代替id,因爲您已經知道您擁有的對象的類別。這樣可以避免一連串的強制轉換:CustomType type1 = [(CustomClass *)obj1 customType];

+0

我已經換掉了第二種方法的其他方法,這是行得通的,謝謝:) –

+0

既然你想'升序:NO','obj1'和'obj2'確實需要顛倒過來。 – Larme

相關問題