[英]How to sort an array both numerically and alphabetically in Swift
假设我有一个数组:
var array = ["5C", "4D", "2H", "13S", "4C", "5H"]
我如何能够对这个数组进行排序,以便新数组的最后一个字符按字母顺序排序,然后以前的数值按数字顺序排序,例如:
["4C", "5C", "4D", "2H", "5H", "13S"]
一般来说,我对编码相对较新,并且对语法有非常基本的掌握。 其他搜索向我展示了如何使用 .sorted function 和 .ascendingOrder 进行数字排序,但我找不到可以同时按字母和数字排序的解决方案。
您必须编写自己的比较器,这在 Swift 中非常方便。
如果最后一个字符相同,则对没有最后一个字符的字符串进行数字排序,否则按最后一个字符排序
let array = ["5C", "4D", "2H", "13S", "4C", "5H"]
let sortedArray = array.sorted { (str1, str2) -> Bool in
if str1.suffix(1) == str2.suffix(1) {
return str1.dropLast().localizedStandardCompare(str2.dropLast()) == .orderedAscending
} else {
return str1.suffix(1) < str2.suffix(1)
}
}
// ["4C", "5C", "4D", "2H", "5H", "13S"]
我的回答显示了如何使用sorted()
将字符串数组排序为“数字”顺序。 这不是OP所要求的。
致 OP:您应该接受 vadian 的回答。 他是第一个正确答案。
但是,我在回答中花了一些时间解释 Swift 闭包语法,所以我将留下答案。
您可以使用数组方法sorted()
,它接受一个比较对象对的闭包,如果第一个项目应该先出现,则返回 true。
然后您可以使用 NSString 方法compare(options:)
进行“数字”字符串比较,其中数字序列被视为字符串中的数字。
这是一个可以对数组进行排序的工作代码片段:
var array = ["5C", "4D", "2H", "13S", "4C", "5H"]
let sorted = array.sorted (by: { (first: String, second: String) -> Bool in
return first.compare(second, options: .numeric) == .orderedAscending
})
The function sorted()
is a "higher order function`, or a function that takes another function as a parameter. For an array of strings, that function takes 2 strings, and returns a Bool. It actually takes a closure rather than a function ,其中闭包是“匿名函数”(没有名称的 function。)
调整 vadian 的代码,为我的代码段提供正确的答案,它看起来像这样:
var array = ["5C", "4D", "2H", "13S", "4C", "5H"]
let sorted = array.sorted (by: { (first: String, second: String) -> Bool in
if first.suffix(1) == second.suffix(1) {
return first.dropLast.compare(second, options: .numeric) == .orderedAscending
} else {
return first.suffix(1) < second.suffix(1)
}
})
您可以使用几个快捷方式重写上述内容:
使用“尾随闭包”,您可以跳过包含闭包作为参数的()
,只需在 function 名称后的大括号中提供闭包。
可以跳过闭包的参数和返回类型的声明,也可以跳过return语句:
let sorted = array.sorted { $0.compare($1, options: .numeric) == .orderedAscending }
对于像 vadian 这样给出正确答案的更复杂的代码,我建议不要使用这样的位置参数。 使用像first
和second
这样的局部变量使代码更易于阅读。
我建议仔细研究 Apple 的 Swift iBooks 中关于闭包的章节,直到您了解闭包的各种表达方式及其不同的快捷语法。 一开始会让人困惑,使用闭包是使用 Swift 的基础。
欢迎来到 StackOverflow!
这些数字代表什么? 我将创建一个struct
model 那个“东西”(我现在称它为Thing
)和 function 可以将String
解析为Thing
,如下所示:
struct Thing: Equatable { // FIXME: Name me something descriptive
let number: Int // FIXME: Name me something descriptive
let letter: Character // FIXME: Name me something descriptive
static func parse(from string: String) -> Thing? {
let numberSegment = string.prefix(while: { $0.isNumber })
guard !numberSegment.isEmpty,
let number = Int(numberSegment) else { return nil }
let letterSegement = string.drop(while: { $0.isNumber })
guard letterSegement.count == 1,
let letter = letterSegement.first else { return nil }
return Thing(number: number, letter: letter)
}
}
然后,您可以遵循Comparable
,通过定义比较运算符<
来定义您希望如何对事物进行排序:
extension Thing: Comparable {
static func < (lhs: Thing, rhs: Thing) -> Bool {
return (lhs.letter, lhs.number) < (rhs.letter, rhs.number)
}
}
从那里开始,只需将所有字符串解析为Thing
并对其进行排序:
let array = ["5C", "4D", "2H", "13S", "4C", "5H"]
let things = array.map { Thing.parse(from: $0)! }
print("Before sorting:")
things.forEach { print("\t\($0)") }
let sortedThings = things.sorted()
print("\nAfter sorting:")
sortedThings.forEach { print("\t\($0)") }
Output:
Before sorting:
Thing(number: 5, letter: "C")
Thing(number: 4, letter: "D")
Thing(number: 2, letter: "H")
Thing(number: 13, letter: "S")
Thing(number: 4, letter: "C")
Thing(number: 5, letter: "H")
After sorting:
Thing(number: 4, letter: "C")
Thing(number: 5, letter: "C")
Thing(number: 4, letter: "D")
Thing(number: 2, letter: "H")
Thing(number: 5, letter: "H")
Thing(number: 13, letter: "S")
欢迎来到 StackOverflow!
这是我的解决方案希望它对你有用,我只是先组织数字,然后与字母进行比较以创建一个新数组:
var array = ["5C", "4D", "2H", "13S", "4C", "5H"]
array = array.sorted { $0.numbersValues < $1.numbersValues }
let str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
var newArrray: [String] = []
for letter in str {
for value in array {
if value.lettersValues.hasPrefix(String(letter)) {
newArrray.append(value)
}
}
}
不要忘记在你的项目中包含这个帮助方法
extension String {
var lettersValues: String {
return self.components(separatedBy: CharacterSet.decimalDigits).joined()
}
var numbersValues: String {
return self.filter { "0"..."9" ~= $0 }
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.