Ios 对多个属性上的NSArray自定义对象进行排序

Ios 对多个属性上的NSArray自定义对象进行排序,ios,objective-c,sorting,nsarray,Ios,Objective C,Sorting,Nsarray,我有一个具有多个属性的自定义对象 一个属性是类型,例如枚举:a、B、C等 这些都有约会 @property (assign) CustomType customType; @property (nonatomic, strong) NSDate *startDate; ... typedef NS_ENUM(NSInteger, CustomType) { A, B, C }; 我想把所有类型为“C”的对象放在第一位,然后按日期顺序排列其余的对象 实现这一目标的最佳方

我有一个具有多个属性的自定义对象

一个属性是类型,例如枚举:a、B、C等

这些都有约会

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

typedef NS_ENUM(NSInteger, CustomType) {
    A,
    B,
    C
};
我想把所有类型为“C”的对象放在第一位,然后按日期顺序排列其余的对象

实现这一目标的最佳方式是什么

我尝试添加多个SortDescriptor,但我只希望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 |
+-------------------------+
我还可以决定我首先想要哪种自定义类型,所以我可能希望B位于顶部,然后按日期选择其余的


将数组分成两组会更容易吗?一组是C,另一组是其他。对每个子组进行排序,然后将它们重新连接在一起

然后,我可以在下面的谓词中选择我想要的顶层组:

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];

按日期排序


在过去,我根据给定属性对数组进行分组,并对单个属性使用自定义排序

@属性(非原子,强)NSString*级别;
NSArray*级别=[array valueForKeyPath:@“@distinctUnionOfObjects.level”];
NSArray*levelsSortOrder=@[“初学者”、“基础”、“中级”、“专家”、“高级”、“开发人员”、“研讨会”];
NSArray*sortedArray=[使用比较器的sortedArray级别:^(id obj1,id obj2){
NSUTEGER index1=[LevelssorOrder indexOfObject:obj1];
NSUTEGER index2=[LevelssorOrder indexOfObject:obj2];
NSComparisonResult ret=传感器名称;
if(index1index2)
{
ret=下移;
}
返回ret;
}];

我喜欢使用Comparator:进行排序,我认为其他方法无法满足您的需要

sortedarrayingcomparator:
在如何排序方面提供了非常大的操作。 其背后的逻辑是: 比较它们之间的两个对象(
obj1
obj2
)。 你决定这两种。 它将遍历整个数组,通过对每个对象逐个进行比较,将得到排序结果。 因此,在块中,您必须明确定义一个对象相对于另一个对象的“优先级”。 这里的
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]];
    }
}];
通过一点重构:

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]];
    }
}];
请注意,
sensorderedescending
sensorderedescending
可能必须反转,我永远不知道使用哪一个,我总是测试


我将两个块中的
id
替换为
CustomClass
,因为您已经知道了对象的类别。这避免了一行强制转换:
CustomType类型1=[(CustomClass*)obj1 CustomType]

我喜欢使用Comparator:
进行排序,我认为其他方法无法满足您的需要

sortedarrayingcomparator:
在如何排序方面提供了非常大的操作。 其背后的逻辑是: 比较它们之间的两个对象(
obj1
obj2
)。 你决定这两种。 它将遍历整个数组,通过对每个对象逐个进行比较,将得到排序结果。 因此,在块中,您必须明确定义一个对象相对于另一个对象的“优先级”。 这里的
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]];
    }
}];
通过一点重构:

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]];
    }
}];
请注意,
sensorderedescending
sensorderedescending
可能必须反转,我永远不知道使用哪一个,我总是测试


我将两个块中的
id
替换为
CustomClass
,因为您已经知道了对象的类别。这避免了一行强制转换:
CustomType类型1=[(CustomClass*)obj1 CustomType]

我已经交换了第二种方法的else,它正在工作,谢谢:)因为你想要
升序:不
obj1
obj2
确实需要反转。我已经交换了第二种方法的else,它正在工作,谢谢:)因为你想要
升序:不
obj1
obj2
确实需要反转。