按字母顺序对带数字的数组进行排序

36
myArray = [Step 6, Step 12, Step 5, Step 14, Step 4, Step 11, Step 16, Step 9, 
Step 3, Step 13, Step 8, Step 2, Step 10, Step 7, Step 1, Step 15]

如何按照这种方式对上述数组进行排序?

[Step 1, Step 2, Step 3, Step 4, ....]

我在 Swift 中使用了这个函数 sort(&myArray,{ $0 < $1 }),但是它被排序成了这样

[Step 1, Step 10, Step 11, Step 12, Step 13, Step 14, Step 15, Step 16, Step 2, 
 Step 3, Step 4, Step 5, Step 6, Step 7, Step 8, Step 9]

对于Objective-C,可以在这里找到答案(例如):http://stackoverflow.com/questions/746200/how-to-add-these-object-with-name-to-the-array-by-this-order。 - Martin R
8个回答

59

另一种选择是使用localizedStandardCompare:。来自文档的描述如下:

当文件名或其他字符串以列表和表格形式呈现且需要进行类似Finder的排序时,应使用此方法。

这将根据当前语言环境适当地对字符串进行排序。例如:

let myArray = ["Step 6", "Step 12", "Step 10"]

let ans = sorted(myArray,{ (s1, s2) in 
    return s1.localizedStandardCompare(s2) == NSComparisonResult.OrderedAscending
})

println(ans)
// [Step 6, Step 10, Step 12]

更新:上面的回答相当古老,适用于Swift 1.2。 Swift 3版本为(感谢@Ahmad):


let ans = myArray.sorted {
    (s1, s2) -> Bool in return s1.localizedStandardCompare(s2) == .orderedAscending
}

如果您想采用不同的方法,请参见https://dev59.com/3l0Z5IYBdhLWcg3wphsE#31209763, 转换成Swift 3,网址为https://dev59.com/3l0Z5IYBdhLWcg3wphsE#39748677


2
让ans = anArray.sorted{$0.localizedStandardCompare($1) == NSComparisonResult.OrderedAscending} 排序后的数组为sortedArray - Leo Dabus
@LeoDabus,这样更短,但我和马丁的(稍微长一点)语法在一瞥之间更容易阅读,特别是对于新手来说。 - Duncan C
嗨马丁,谢谢你的回答,对我来说这是最好的答案,也喜欢Ludovic的评论。 - Dennis Garcia
1
Swift 3版本: let myArray = ["步骤6", "步骤12", "步骤10"] let ans = myArray.sorted { (s1, s2) -> Bool in return s1.localizedStandardCompare(s2) == ComparisonResult.orderedAscending } - Ahmad F
1
@MartinR **Xcode 13+ • iOS 15+**,你可以使用KeyPathComparator传递self和String.Comparator.localizedStandard Swift来对包含字符串和数字的数组进行排序 - Leo Dabus
显示剩余3条评论

18

Duncan C的答案 的Swift 3版本是:

let myArray = ["Step 6", "Step 12", "Step 10"]

let sortedArray = myArray.sorted {
    $0.compare($1, options: .numeric) == .orderedAscending
}

print(sortedArray) // ["Step 6", "Step 10", "Step 12"]

或者,如果你想原地排序数组:

var myArray = ["Step 6", "Step 12", "Step 10"]

myArray.sort {
    $0.compare($1, options: .numeric) == .orderedAscending
}

print(myArray) // ["Step 6", "Step 10", "Step 12"]

7
NSString有丰富的字符串比较方法,您可以使用方法compare:options:
您需要使用NSNumericSearch选项。如果您阅读该选项的描述,则会发现:

在字符串中的数字使用数字值进行比较,即Name2.txt < Name7.txt < Name25.txt。

因此,您可以编写一个使用该函数实现所需功能的Swift排序行。
类似于以下内容:
let myArray = ["Step 6", "Step 12", "Step 10"]

let ans = myArray.sorted {
    (first, second) in
    first.compare(second, options: .NumericSearch) == NSComparisonResult.OrderedAscending
}

println(ans)
// [Step 6, Step 10, Step 12]

1
不需要将类型转换为 NSString。只要导入了 Foundation 框架,String 的方法也是可用的。 - Martin R
嗨,Duncan C,感谢您抽出时间回答我的问题,您的答案是正确的,我很感激,但我找到了一个更好的答案。 - Dennis Garcia
如果你找到了更好的答案,那么你应该将其作为自己问题的答案发布并接受它。 - Duncan C

6

在Swift 2中:

import Foundation

let myArray = ["Step 6", "Step 12", "Step 10"]

extension String {
  func extractIntFromEnd() -> Int? {
    return self.componentsSeparatedByString(" ").last.flatMap{Int($0)}
  }
}

let ans = myArray.sort {
  (first, second) in
  first.extractIntFromEnd() < second.extractIntFromEnd()
}

在Swift 1中:

let myArray = ["Step 6", "Step 12", "Step 10"]

extension String {
  func extractIntFromEnd() -> Int? {
    return self.componentsSeparatedByString(" ").last.flatMap{$0.toInt()}
  }
}

let ans = myArray.sorted {
  (first, second) in
  first.extractIntFromEnd() < second.extractIntFromEnd()
}

在这两种情况下,都是对这个数组进行操作:
let myArray = [
  "Step 6" ,
  "Step 12",
  "Step 5" ,
  "Step 14",
  "Step 4" ,
  "Step 11",
  "Step 16",
  "Step 9" ,
  "Step 3" ,
  "Step 13",
  "Step 8" ,
  "Step 2" ,
  "Step 10",
  "Step 7" ,
  "Step 1" ,
  "Step 15"
]

我会给你这个答案:

["Step 1", "Step 2", "Step 3", "Step 4", "Step 5", "Step 6", "Step 7", "Step 8", "Step 9", "Step 10", "Step 11", "Step 12", "Step 13", "Step 14", "Step 15", "Step 16"]

在Swift 2.0版本中,你应该能够执行last.flatMap(Int.init),但由于某些原因它无法正常工作。即使像["1", "2"].flatMap(Int.init)这样的操作也会导致我的playground崩溃。看起来像是一个bug。

嗨,oisdk,感谢你抽出时间回答我的问题。我很感激你的回答,虽然它也是正确的,但我找到了一个更好的答案。 - Dennis Garcia

1

让我的数组为["Step 6", "Step 12", "Step 10"]

让排序后的数组为myArray.sorted(by: { x, y in return x.field.name.compare(y.field.name, options: .numeric, range: nil, locale: nil) == .orderedAscending })


0

Swift 2.0 中的排序 演示链接,从 "sorted(myArray,{})" 改为 "myArray.sort({})" 的语法变化。可扩展协议。

let myArray = ["Step 6", "Step 12", "Step 10"]
let sortedArray = myArray.sort({ x, y in
    return x.localizedStandardCompare(y) == NSComparisonResult.OrderedAscending
})

dump(sortedArray)

Swift 1.2 示例


0
NSArray *assorted = [@"1 2 3 9 ; : 구 , 결 A B C Z ! á" componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSArray *sorted = [assorted sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
    /* NSOrderedAscending, NSOrderedSame, NSOrderedDescending */
    BOOL isPunct1 = [[NSCharacterSet punctuationCharacterSet] characterIsMember:[(NSString*)obj1 characterAtIndex:0]];
    BOOL isPunct2 = [[NSCharacterSet punctuationCharacterSet] characterIsMember:[(NSString*)obj2 characterAtIndex:0]];
    if (isPunct1 && !isPunct2) {
        return NSOrderedAscending;
    } else if (!isPunct1 && isPunct2) {
        return NSOrderedDescending;
    }
    return [(NSString*)obj1 compare:obj2 options:NSDiacriticInsensitiveSearch|NSCaseInsensitiveSearch|NSNumericSearch]|;         
}];

-1

您可以使用一个循环,其次数等于数组的长度,即for(i=0;i<myArray.length;i++),然后可以使用一个变量按顺序对它们进行排序,例如:

for (int i = 0; i < myArray.length; i++) 
{
  for (int j = i + 1; j < n; j++) 
  {
    if (a[i] > a[j]) 
    {
      temp = a[i];
      a[i] = a[j];
      a[j] = temp;
    }
  }
}

这并没有解决按照数字值对字符串进行排序的问题(例如,“Step 6” < “Step 10” < “Step 12”)。此外,这在Swift中无法编译。 - Martin R

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接