使用 NSComparisonResult 对 NSArray 进行递归排序
Recursive sorting of an NSArray using an NSComparisonResult
我正在尝试对本身包含不同类型结构的数组进行排序。现在我似乎无法让它在根数组中有子数组时对其进行递归排序。
在下面的代码中,我有一个包含两个子数组的测试数组,但由于某种原因返回的根数组正在移动已排序的子数组中的项目。使用递归对子数组进行了正确排序,但在递归之后,子数组失去了之前的排序。如果能提供任何帮助,我将不胜感激。
已排序子数组的输出:
(
A,
b,
C,
c,
Cc,
cc,
CC,
hhh,
x,
z
)
这是排序后的根数组的输出(不是我想要的):
(
(
z,
A,
b,
hhh,
x,
Cc,
C,
cc,
CC,
c
),
(
z,
A,
b,
hhh,
x,
Cc,
C,
cc,
CC,
c
)
)
代码:
- (void)test
{
NSArray *testArr = @[ @[@"z",@"A",@"b",@"hhh",@"x",@"Cc",@"C",@"cc",@"CC",@"c"],
@[@"z",@"A",@"b",@"hhh",@"x",@"Cc",@"C",@"cc",@"CC",@"c"]
];
self.t = [NSMutableArray arrayWithArray:[self sortedArray:testArr]];
NSLog(@"%@",self.t);
}
- (NSArray *)sortedArray:(NSArray *)input
{
NSArray *newArray = [input sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2)
{
NSString *nameOne = @"";
NSString *nameTwo = @"";
if ([obj1 isKindOfClass:[NSString class]])
{
nameOne = obj1;
nameTwo = obj2;
}
else if ([obj1 isKindOfClass:[NSArray class]])
{
NSArray *sorted1stArray = [self sortedArray:obj1];
NSArray *sorted2ndArray = [self sortedArray:obj2];
NSLog(@"%@",sorted1stArray);
NSLog(@"%@",sorted2ndArray);
if ([sorted1stArray.firstObject isKindOfClass:[NSDictionary class]])
{
NSDictionary *firstDict = sorted1stArray.firstObject;
NSDictionary *secondDict = sorted2ndArray.firstObject;
if (firstDict[@"Title"])
{
nameOne = firstDict[@"Title"];
nameTwo = secondDict[@"Title"];
}
}
else if ([sorted1stArray.firstObject isKindOfClass:[NSString class]])
{
nameOne = sorted1stArray.firstObject;
nameTwo = sorted2ndArray.firstObject;
}
}
else if ([obj1 isKindOfClass:[NSDictionary class]])
{
if (obj1[@"Title"])
{
nameOne = obj1[@"Title"];
nameTwo = obj2[@"Title"];
}
}
return [nameOne localizedCaseInsensitiveCompare:nameTwo];
}];
return newArray;
}
每次比较都会调用比较器。这意味着它会为每个元素调用多次。然后对每个子数组进行多次排序。
在第一次排序之前,你应该回溯结构并首先对内部结构进行排序,而不是使用递归比较器。换句话说,不要将比较器与排序混用。保持独立。
代码可以具有以下结构:
- (NSArray *)sortedArray:(NSArray *)input {
//1. sort every subelement in input recursively
//2. sort input
}
另请注意,子结构的排序不会反映在结果中。它没有保存在任何地方,它只是在比较器中临时创建的。
如果它只是数组中的数组中的字符串,为什么递归解决的麻烦?
NSArray *testArr = @[[@[@"z",@"A",@"b",@"hhh",@"x",@"Cc",@"C",@"cc",@"CC",@"c"] mutableCopy],
[@[@"z",@"A",@"b",@"hhh",@"x",@"Cc",@"C",@"cc",@"CC",@"c"] mutableCopy
];
[testArr enumerateObjectsUsingBlock:^(NSMutableArray *subarray, NSUInteger idx, BOOL *stop) {
[subarray sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [obj1 localizedCaseInsensitiveCompare:obj2];
}];
}];
… needs to be sorted using a certain sequence (not just A-Z)
查找将是一个合理的解决方案,如我在此处所示:,或者您自己的比较方法需要 return NSComparisonResult
enum {
NSOrderedAscending = -1,
NSOrderedSame,
NSOrderedDescending
};
typedef NSInteger NSComparisonResult;
您可以在类别中定义该方法
@implementation NSString (MySorting)
-(NSComparisonResult)localizedCaseInsensitiveCompareLongestFirst:(NSString *)string
{
if ([self length] > [string length]) {
return NSOrderedAscending;
} else if ([self length] < [string length]) {
return NSOrderedDescending;
} else {
return [self localizedCaseInsensitiveCompare:string];
}
}
@end
现在修改第一个密码
NSArray *testArr = @[ [@[@"z",@"A",@"b",@"hhh",@"x",@"Cc",@"C",@"cc",@"CC",@"c"] mutableCopy],
[@[@"z",@"A",@"b",@"hhh",@"x",@"Cc",@"C",@"cc",@"CC",@"c"] mutableCopy]
];
[testArr enumerateObjectsUsingBlock:^(NSMutableArray *subarray, NSUInteger idx, BOOL *stop) {
[subarray sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [obj1 localizedCaseInsensitiveCompareLongestFirst:obj2];
}];
}];
我们有
的自定义排序
(
(
hhh,
Cc,
cc,
CC,
A,
b,
C,
c,
x,
z
),
(
hhh,
Cc,
cc,
CC,
A,
b,
C,
c,
x,
z
)
)
我正在尝试对本身包含不同类型结构的数组进行排序。现在我似乎无法让它在根数组中有子数组时对其进行递归排序。
在下面的代码中,我有一个包含两个子数组的测试数组,但由于某种原因返回的根数组正在移动已排序的子数组中的项目。使用递归对子数组进行了正确排序,但在递归之后,子数组失去了之前的排序。如果能提供任何帮助,我将不胜感激。
已排序子数组的输出:
(
A,
b,
C,
c,
Cc,
cc,
CC,
hhh,
x,
z
)
这是排序后的根数组的输出(不是我想要的):
(
(
z,
A,
b,
hhh,
x,
Cc,
C,
cc,
CC,
c
),
(
z,
A,
b,
hhh,
x,
Cc,
C,
cc,
CC,
c
)
)
代码:
- (void)test
{
NSArray *testArr = @[ @[@"z",@"A",@"b",@"hhh",@"x",@"Cc",@"C",@"cc",@"CC",@"c"],
@[@"z",@"A",@"b",@"hhh",@"x",@"Cc",@"C",@"cc",@"CC",@"c"]
];
self.t = [NSMutableArray arrayWithArray:[self sortedArray:testArr]];
NSLog(@"%@",self.t);
}
- (NSArray *)sortedArray:(NSArray *)input
{
NSArray *newArray = [input sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2)
{
NSString *nameOne = @"";
NSString *nameTwo = @"";
if ([obj1 isKindOfClass:[NSString class]])
{
nameOne = obj1;
nameTwo = obj2;
}
else if ([obj1 isKindOfClass:[NSArray class]])
{
NSArray *sorted1stArray = [self sortedArray:obj1];
NSArray *sorted2ndArray = [self sortedArray:obj2];
NSLog(@"%@",sorted1stArray);
NSLog(@"%@",sorted2ndArray);
if ([sorted1stArray.firstObject isKindOfClass:[NSDictionary class]])
{
NSDictionary *firstDict = sorted1stArray.firstObject;
NSDictionary *secondDict = sorted2ndArray.firstObject;
if (firstDict[@"Title"])
{
nameOne = firstDict[@"Title"];
nameTwo = secondDict[@"Title"];
}
}
else if ([sorted1stArray.firstObject isKindOfClass:[NSString class]])
{
nameOne = sorted1stArray.firstObject;
nameTwo = sorted2ndArray.firstObject;
}
}
else if ([obj1 isKindOfClass:[NSDictionary class]])
{
if (obj1[@"Title"])
{
nameOne = obj1[@"Title"];
nameTwo = obj2[@"Title"];
}
}
return [nameOne localizedCaseInsensitiveCompare:nameTwo];
}];
return newArray;
}
每次比较都会调用比较器。这意味着它会为每个元素调用多次。然后对每个子数组进行多次排序。
在第一次排序之前,你应该回溯结构并首先对内部结构进行排序,而不是使用递归比较器。换句话说,不要将比较器与排序混用。保持独立。
代码可以具有以下结构:
- (NSArray *)sortedArray:(NSArray *)input {
//1. sort every subelement in input recursively
//2. sort input
}
另请注意,子结构的排序不会反映在结果中。它没有保存在任何地方,它只是在比较器中临时创建的。
如果它只是数组中的数组中的字符串,为什么递归解决的麻烦?
NSArray *testArr = @[[@[@"z",@"A",@"b",@"hhh",@"x",@"Cc",@"C",@"cc",@"CC",@"c"] mutableCopy],
[@[@"z",@"A",@"b",@"hhh",@"x",@"Cc",@"C",@"cc",@"CC",@"c"] mutableCopy
];
[testArr enumerateObjectsUsingBlock:^(NSMutableArray *subarray, NSUInteger idx, BOOL *stop) {
[subarray sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [obj1 localizedCaseInsensitiveCompare:obj2];
}];
}];
… needs to be sorted using a certain sequence (not just A-Z)
查找将是一个合理的解决方案,如我在此处所示:
enum {
NSOrderedAscending = -1,
NSOrderedSame,
NSOrderedDescending
};
typedef NSInteger NSComparisonResult;
您可以在类别中定义该方法
@implementation NSString (MySorting)
-(NSComparisonResult)localizedCaseInsensitiveCompareLongestFirst:(NSString *)string
{
if ([self length] > [string length]) {
return NSOrderedAscending;
} else if ([self length] < [string length]) {
return NSOrderedDescending;
} else {
return [self localizedCaseInsensitiveCompare:string];
}
}
@end
现在修改第一个密码
NSArray *testArr = @[ [@[@"z",@"A",@"b",@"hhh",@"x",@"Cc",@"C",@"cc",@"CC",@"c"] mutableCopy],
[@[@"z",@"A",@"b",@"hhh",@"x",@"Cc",@"C",@"cc",@"CC",@"c"] mutableCopy]
];
[testArr enumerateObjectsUsingBlock:^(NSMutableArray *subarray, NSUInteger idx, BOOL *stop) {
[subarray sortUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [obj1 localizedCaseInsensitiveCompareLongestFirst:obj2];
}];
}];
我们有
的自定义排序(
(
hhh,
Cc,
cc,
CC,
A,
b,
C,
c,
x,
z
),
(
hhh,
Cc,
cc,
CC,
A,
b,
C,
c,
x,
z
)
)