【问题标题】:Sort NSArray to a particular sequence using an NSComparisonResult使用 NSComparisonResult 将 NSArray 排序到特定序列
【发布时间】:2015-06-13 03:43:26
【问题描述】:

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

我正在尝试将 Emoji 的权重放在顶部(Emojis 的序列无关紧要),然后是 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;
}

【问题讨论】:

    标签: ios objective-c nsarray comparator


    【解决方案1】:

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

    - (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;
    }
    

    【讨论】:

    • 支票:character &gt; 255 是否说它超出了 ascii 的范围,但它仍然可能不是表情符号?
    • 是的。你是对的。以下是关于检测表情符号的答案:stackoverflow.com/a/14472163/4815066
    • 是的。但是已经有一年多的历史了,它可能无法与 iOS 8.3 中的新表情符号一起正常工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-16
    • 1970-01-01
    • 2021-08-27
    • 2012-09-08
    • 1970-01-01
    相关资源
    最近更新 更多