【问题标题】:How to sort a stringsarray that contain numbers and names in iOS如何在iOS中对包含数字和名称的字符串数组进行排序
【发布时间】:2014-09-09 15:33:21
【问题描述】:

我有一个包含字符串的数组并想要对其进行排序。 到目前为止,很容易。

我只是用

NSSortDescriptor *sort [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
[list sortUsingDescriptors:[NSArray arrayWithObject:sort] ];

这里的问题是,当我将它用于“ccccc,aab,bba,123”之类的列表时 他将其分类为“123,aab,bba,ccccc”。 我想将其排序为“aab, bba, ccccc, 123”

是否有一个 iOS 功能可以对将数字放在列表末尾进行排序?这些数字也是 ofc 字符串。

感谢大家的帮助。

【问题讨论】:

    标签: ios sorting


    【解决方案1】:

    在标准排序中,通常将数字放在字母之前。如果你想要最后的数字,你将不得不做一些操作。

    您可以使用NSPredicate 只获取一个数组中的数字,然后只获取另一个数组中的字母,最后将它们组合起来以获取最后的数字。

    // Get just the letters
    NSPredicate *predLetters = [NSPredicate predicateWithFormat:@"name MATCHES %@",@"^\\p{letter}.*"];
    NSArray *tempLetters = [[list copy] sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]];
    tempLetters = [tempLetters filteredArrayUsingPredicate:predLetters];
    
    // Get just the numbers
    NSPredicate *predNumbers = [NSPredicate predicateWithFormat:@"NOT (name MATCHES %@)",@"^\\p{letter}.*"];
    NSArray *tempNumbers = [[list copy] sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]];
    tempNumbers = [tempNumbers filteredArrayUsingPredicate:predNumbers];
    
    // Combine arrays
    NSMutableArray *tempCombined = [[NSMutableArray alloc] initWithArray:tempLetters];
    [tempCombined addObjectsFromArray:tempNumbers];
    
    // Rename to 'list'
    list = [tempCombined copy];
    

    澄清:此代码仅适用于name 的第一个字符。我从您的问题中假设您不会有任何names 既有字母又有数字。如果你这样做了,那么过滤器将只删除第一个字符,name 中的其余字符将根据标准约定进行排序。如果您希望始终首先处理字母,即使它们是字符串中的第 5 个字符,您可能必须设置一个递归函数或其他东西来处理对包含字母和数字的 name 进行排序,例如.

    编辑:感谢@Nerethar 的语法修复。

    【讨论】:

    • 这看起来很有希望,我明天试试这个并发布结果。谢谢。
    • 我尝试了代码并且不得不做一些小改动,请查看我的答案。我希望版主编辑您的帖子,或者您可以在其中编辑解决方案 + 解释,然后我会将您的帖子标记为有效答案,以便您获得荣誉。谢谢
    【解决方案2】:

    它现在按照我想要的方式工作,对 GeneralMike 的代码进行了少量修改,因此归功于他。 我在这里发布了工作代码,并解释了更改。

    NSSortDescriptor *sort [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
    
    // Get just the letters
    NSPredicate *predLetters = [NSPredicate predicateWithFormat:@"name MATCHES %@",@"^\\p{letter}.*"];
    NSArray *tempLetters = [[list copy] sortedArrayUsingDescriptors:@[sort]];
    tempLetters = [tempLetters filteredArrayUsingPredicate:predLetters];
    
    // Get just the numbers
    NSPredicate *predNumbers = [NSPredicate predicateWithFormat:@"NOT (name MATCHES %@)",@"^\\p{letter}.*"];
    NSArray *tempNumbers = [[list copy] sortedArrayUsingDescriptors:@[sort]];
    tempNumbers = [tempNumbers filteredArrayUsingPredicate:predNumbers];
    
    // Combine arrays
    NSMutableArray *tempCombined = [[NSMutableArray alloc] initWithArray:tempLetters];
    [tempCombined addObjectsFromArray:tempNumbers];
    
    // Rename to 'list'
    list = [tempCombined copy];
    

    显然你不能使用 来比较我找到的字符串。但是要检查它是否以字母开头,这个正则表达式可以正常工作。欲了解更多信息,请查看: How can i filter NSMutableArray by firstName with non-alphabetical characters

    其他更改只是语法原因,但正如 GeneralMike 之前所说,他没有时间实际检查它。

    filteredArrayWithPredicate 需要被filteredArrayUsingPredicate

    sortedArrayUsingDescriptors:sort需要排序ArrayUsingDescriptors:@[sort] 否则你会得到一个演员警告。

    版主是否可以将工作代码和解释编辑到他的帖子中,以便他获得答案和赞成票?

    谢谢

    【讨论】:

      【解决方案3】:

      使用自定义比较器:

      sortedArray = [list sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
          id aValue = [a valueForKey:@"name"];
          id bValue = [b valueForKey:@"name"];
          //check if both aValue and bValue are numbers or if both aValue and bValue are both strings
          //if so, then use normal sort order
          //else, if aValue is a string, and bValue is a number, then return NSOrderedAscending
          //else (aValue is a number, and bValue is a string), return NSOrderedDescending
      }];
      

      【讨论】:

      • 如果您希望“Joe Smith”在“Joe 123”之前在“John ABC”之前在“John 456”之前在“John 1234”之前。
      猜你喜欢
      • 2019-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-18
      • 2016-07-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多