ios - 使用 NSComparisonResult 将 NSArray 排序为特定序列

标签 ios objective-c nsarray comparator

我正在尝试使用 NSComparisonResult 按特定顺序对我的数组进行排序。我无法弄清楚如何实现我想要的序列。

我正在尝试将表情符号置于顶部(表情符号的顺序无关紧要),然后是 A-Z 字母,在大写字母之前给予小写字母权重,然后是数字,然后是标点符号,然后是符号,等等其他之后我现在不关心。到目前为止,我已经很接近了,但我仍然没有达到我想要的效果。

我尝试实现的序列输出如下所示:

("\Ud83d\Ude03",
a,
A,
aa,
aA,
ab,
aB,
a1,
A1,
1,
01,
11,
001,
0001,
1001,
"#",
"#a",
"#1",
"$12",
"$0012")

基于这个数组作为输入:

@[ @"a", @"aA", @"aa", @"A", @"aB", @"11", @"1001", @"ab", @"001", @"01", 
   @"a1", @"A1", @"😃", @"0001", @"1", @"#", @"$12", @"$0012", @"#a", @"#1" ];

但这是我得到的输出:

("\Ud83d\Ude03",
a,
A,
aA,
aa,
aB,
ab,
a1,
A1,
0001,
001,
01,
1,
1001,
11,
"#a",
"#1",
"$0012",
"$12",
"#")

代码:

- (NSArray *)sortedArray:(NSArray *)input
{
    NSArray *newArray = [input sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2)
    {
        NSString *nameOne = obj1;
        NSString *nameTwo = obj2;

        NSString *startOne;
        NSString *startTwo;

        NSInteger currentIndex = 0;
        NSInteger maxIndex = (nameOne.length < nameTwo.length) ? nameOne.length : nameTwo.length;

        NSCharacterSet *decimalDigitCharSet = [NSCharacterSet decimalDigitCharacterSet];

        NSCharacterSet *punctuationCharSet = [NSCharacterSet punctuationCharacterSet];

        NSCharacterSet *symbolCharSet = [NSCharacterSet symbolCharacterSet];

        NSMutableCharacterSet *nonPriorityCharSet = [[NSMutableCharacterSet alloc]init];

        [nonPriorityCharSet formUnionWithCharacterSet:punctuationCharSet];
        [nonPriorityCharSet formUnionWithCharacterSet:symbolCharSet];

        do
        {
            if (currentIndex < maxIndex)
            {
                startOne = [nameOne substringWithRange:NSMakeRange(currentIndex, 1)];
                startTwo  = [nameTwo substringWithRange:NSMakeRange(currentIndex, 1)];
                currentIndex++;
            }
            else
            {
                if (nameOne.length == nameTwo.length)
                {
                    return NSOrderedSame;
                }
                else
                {
                    return (nameOne.length < nameTwo.length) ? NSOrderedAscending : NSOrderedDescending;
                }
            }
        }
        while ([startOne isEqualToString:startTwo]);
        {
            NSRange rangeOne = [startOne rangeOfCharacterFromSet:nonPriorityCharSet];
            NSRange rangeTwo = [startTwo rangeOfCharacterFromSet:nonPriorityCharSet];

            if (rangeOne.length > 0 || rangeTwo.length > 0)
            {
                return (rangeOne.length > 0) ? NSOrderedDescending : NSOrderedAscending;
            }

            NSRange decimalRangeOne = [startOne rangeOfCharacterFromSet:decimalDigitCharSet];
            NSRange decimalRangeTwo = [startTwo rangeOfCharacterFromSet:decimalDigitCharSet];

            if (decimalRangeOne.length > 0 || decimalRangeTwo.length > 0)
            {
                if (decimalRangeOne.length == decimalRangeTwo.length)
                {
                    return (startOne.intValue > startTwo.intValue) ? NSOrderedDescending : NSOrderedAscending;
                }
                else if (decimalRangeOne.length > decimalRangeTwo.length)
                {
                    return NSOrderedDescending;
                }
                else if (decimalRangeTwo.length > decimalRangeOne.length)
                {
                    return NSOrderedAscending;
                }
            }
        }

        return  [nameOne localizedCaseInsensitiveCompare:nameTwo];
   }];

    return newArray;
}

最佳答案

你的开始很好。但是您没有正确检查您设置的所有规则。我根据您的规则创建了一些类别,并使用它们进行排序。

- (NSArray *)sortedArray:(NSArray *)input
{
    __block id blocksafeSelf = self;

    NSArray *newArray = [input sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
        NSString *nameOne = obj1;
        NSString *nameTwo = obj2;

        NSInteger currentIndex = 0;
        unichar charOne = [nameOne characterAtIndex:0];
        unichar charTwo = [nameTwo characterAtIndex:0];

        short maxLength = MIN(nameOne.length, nameTwo.length);

        do {
            charOne = [nameOne characterAtIndex:currentIndex];
            charTwo = [nameTwo characterAtIndex:currentIndex];
            currentIndex ++;
        }
        while (charOne == charTwo && currentIndex < maxLength);

        short oneCategory = [blocksafeSelf getCharCategory:charOne];
        short twoCategory = [blocksafeSelf getCharCategory:charTwo];

        if (oneCategory != twoCategory) {
            return oneCategory > twoCategory;
        }
        else if (oneCategory != 1) {
            if (nameOne.length != nameTwo.length) {
                return nameOne.length > nameTwo.length;
            }
            else {
                return charOne > charTwo;
            }
        }
        else {
            if (nameOne.length != nameTwo.length) {
                return nameOne.length > nameTwo.length;
            }
            else {
                oneCategory = [blocksafeSelf getLetterCategory:charOne];
                twoCategory = [blocksafeSelf getLetterCategory:charTwo];

                if (oneCategory == twoCategory) {
                    return charOne > charTwo;
                }
                else {
                    unichar tempCharOne = oneCategory == 7 ? charOne + 32 : charOne;
                    unichar tempCharTwo = twoCategory == 7 ? charTwo + 32 : charTwo;

                    if (tempCharOne != tempCharTwo) {
                        return tempCharOne > tempCharTwo;
                    }
                    else {
                        return oneCategory > twoCategory;
                    }
                }
            }
        }
        return  [nameOne localizedCaseInsensitiveCompare:nameTwo];
    }];

    return newArray;
}

- (short)getCharCategory:(unichar)character {

    if (character > 255) {     // emoji
        return 0;
    }

    NSCharacterSet *letterCaseCharSet = [NSCharacterSet letterCharacterSet];
    if  ([letterCaseCharSet characterIsMember:character]) return 1;

    NSCharacterSet *decimalDigitCharSet = [NSCharacterSet decimalDigitCharacterSet];
    if  ([decimalDigitCharSet characterIsMember:character]) return 2;

    NSCharacterSet *punctuationCharSet = [NSCharacterSet punctuationCharacterSet];
    if  ([punctuationCharSet characterIsMember:character]) return 3;

    NSCharacterSet *symbolCharSet = [NSCharacterSet symbolCharacterSet];
    if  ([symbolCharSet characterIsMember:character]) return 4;

    return 5;

}

- (short)getLetterCategory:(unichar)character {

    NSCharacterSet *lowerCaseCharSet = [NSCharacterSet lowercaseLetterCharacterSet];
    if  ([lowerCaseCharSet characterIsMember:character]) return 6;

    return 7;
}

关于ios - 使用 NSComparisonResult 将 NSArray 排序为特定序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30814834/

相关文章:

ios - 如何在 Objective-C 、iOS 中将 NSMutableArray 数组分成两个单独的数组或两个可变数组

ios - 不断增加应用程序内存(IOAccelResource)

ios - 在单数组中转换字典数组

ios - Xcode 7 - SVN 提交失败错误 - 怎么办?

ios - 以编程方式从 collectionView Cell didSelectItemAt 推送到新的 ViewController - swift

iphone - 如何检索 UISwitch 的 UITableView 行号?

objective-c - CGSize中使用的字体名称 sizeWithFont :?

iphone - 我应该什么时候释放我的阵列?

ios - 无法将类型 '()' (0x2c2fb50) 的值转换为 'Swift.AnyObject

ios - Swift:解雇ViewController并实例化另一个ViewController