8

我正在尝试对 iOS UITableView 对象进行排序。我目前正在使用以下代码:

// Sort terms alphabetically, ignoring case
[self.termsList sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)];

这对我的列表进行排序,忽略大小写。但是,也可以忽略标点符号。例如:

c.a.t.
car
cat

应按如下方式排序:

car
c.a.t.
cat

(实际上,两只猫(猫或猫)中的哪一只先来并不重要,只要它们彼此相邻排序即可)。

有没有一种简单的方法来解决这个问题?我认为解决方案将涉及从字符串中提取字母数字字符,然后比较它们,然后将它们返回到以前的状态,并再次包含非字母数字字符。

事实上,我真正关心的唯一字符是句点 (.) 但如果有一个解决方案可以轻松涵盖所有标点符号,那么了解它会很有用。

注意:一个月前我问过这个关于 Java 的完全相同的问题。现在,我正在 Objective-C 中创建相同的解决方案。我想知道 iOS API 是否有任何技巧可以让这变得简单......

编辑:我尝试使用以下代码去除标点符号并填充我排序的另一个数组(由@tiguero 建议)。但是,我不知道如何做最后一步:根据第二个数组的顺序实际对第一个数组进行排序。这是我的代码:

    NSMutableArray *arrayWithoutPunctuation = [[NSMutableArray alloc] init];
    for (NSString *item in arrayWithPunctuation)
    {
        // Replace hyphens/periods with spaces
        item = [item stringByReplacingOccurrencesOfString:@"-" withString:@" "]; // ...hyphens
        item = [item stringByReplacingOccurrencesOfString:@"." withString:@" "]; // ...periods
        [arrayWithoutPunctuation addObject:item];
    }
    [arrayWithoutPunctuation sortUsingSelector:@selector(localizedCaseInsensitiveCompare:)];

这提供了已排序的 'arrayWithoutPunctuation',但当然不包含 punctuation。这不好,因为虽然它现在排序很好,但它不再包含对数组至关重要的标点符号。我需要做的是根据'arrayWithoutPunctuation'的顺序对'arrayWithPunctuation'进行排序......任何帮助表示赞赏。

4

3 回答 3

9

您可以在 an 上使用比较块NSArray,您的代码将如下所示:

NSArray* yourStringList = [NSArray arrayWithObjects:@"c.a.t.", @"car", @"cat", nil];
NSArray* yourStringSorted = [yourStringList sortedArrayUsingComparator:^(id a, id b){
        NSString* as = (NSString*)a;
        NSString* bs = (NSString*)b;

        NSCharacterSet *unwantedChars = [NSCharacterSet characterSetWithCharactersInString:@"\\.:',"];
        //Remove unwanted chars
        as = [[as componentsSeparatedByCharactersInSet: unwantedChars] componentsJoinedByString: @""];
        bs = [[as componentsSeparatedByCharactersInSet: unwantedChars] componentsJoinedByString: @""];

        // make the case insensitive comparison btw your two strings
        return [as caseInsensitiveCompare: bs];
    }];

这可能不是最有效的代码,实际上另一种选择是首先迭代您的数组并删除所有不需要的字符并将 aselector与该caseInsensitiveCompare方法一起使用:

 NSString* yourStringSorted = [yourStringList sortedArrayUsingSelector:@selector(caseInsensitiveCompare:)];
于 2012-10-24T22:41:53.203 回答
2

这更清洁,更高效:

NSArray* strings = @[@".....c",@"a.",@"a",@"b",@"b...",@"a..,"];
NSArray* sorted_strings = [strings sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    NSString* a = [obj1 stringByTrimmingCharactersInSet:[NSCharacterSet punctuationCharacterSet]];
    NSString* b = [obj2 stringByTrimmingCharactersInSet:[NSCharacterSet punctuationCharacterSet]];
    return [a caseInsensitiveCompare:b];
}];

为了真正的效率,我会编写一个忽略标点符号的比较方法,这样就不需要内存分配来进行比较。

于 2012-11-06T10:39:03.977 回答
1

我的解决方案是将每个字符串分组为具有两个属性的自定义对象

  • 原始字符串
  • 没有标点的字符串

...然后根据没有标点符号的字符串对对象进行排序。

Objective C 有一些方便的方法来做到这一点。所以假设我们在这个对象中有两个字符串:

NSString *myString;
NSString *modified;

首先,将您的自定义对象添加到数组中

NSMutableArray *myStrings = [[NSMutableArray alloc] init];
[myStrings addObject: ...];

然后,使用方便的 NSSortDescriptor按修改后的变量对数组进行排序。

//You can specify the variable name to sort by
//Sorting is done according to the locale using localizedStandardCompare
NSSortDescriptor *mySortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"modified" ascending:YES selector:@selector(localizedStandardCompare:)];
[myStrings sortedArrayUsingDescriptors:@[ mySortDescriptor ]];

瞧!您的对象(和字符串)已排序。 有关 NSSortDescriptor 的更多信息...

于 2012-10-30T23:37:30.200 回答