使用 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
    )
)