Swift用字符串和数字对数组进行排序 [英] Swift sort an array with strings and numbers
问题描述
我有一个字符串数组,
let array = [ "10", "1", "101", "NA", "100", "20", "210", "200", "NA", "7" ]
我想让输出按升序排序,
I would like to get the output sorted in ascending as,
let sorted = [ "1", "7", "10", "20", "100", "101", "200", "210", "NA", "NA" ]
我尝试使用 sorted 命令,但遇到超过 2 位数字时不起作用,例如:100、101、200 等
I tried using the sorted command but it does not work when it encounters more than 2 digits e.g.: 100, 101, 200 etc.
array.sorted { $0? < $1? }
获得这个的简单方法是什么?
What would be the simple way to get this?
推荐答案
编辑/更新:Xcode 11.3 • Swift 5.2 或更高版本
您可以使用字符串方法localizedStandardCompare
(变音符号和不区分大小写):
You can use String method localizedStandardCompare
(diacritics and case insensitive):
let array = [ "10", "1", "101", "NA", "100", "20", "210", "200", "NA", "7" ]
let sorted = array.sorted {$0.localizedStandardCompare($1) == .orderedAscending}
print(sorted) // ["1", "7", "10", "20", "100", "101", "200", "210", "NA", "NA"]
或在 MutableCollection 上使用方法 sort(by:)
:
var array = [ "10", "1", "101", "NA", "100", "20", "210", "200", "NA", "7" ]
array.sort {$0.localizedStandardCompare($1) == .orderedAscending}
print(array) // ["1", "7", "10", "20", "100", "101", "200", "210", "NA", "NA"]
您还可以实现自己的本地化标准排序方法扩展集合:
You can also implement your own localized standard sort method extending Collection:
public extension Sequence where Element: StringProtocol {
func localizedStandardSorted(ascending: Bool = true) -> [Element] {
let result: ComparisonResult = ascending ? .orderedAscending : .orderedDescending
return sorted { $0.localizedStandardCompare($1) == result }
}
}
let array = [ "10", "1", "101", "NA", "100", "20", "210", "200", "NA", "7" ]
let sorted = array.localizedStandardSorted()
print(sorted) // ["1", "7", "10", "20", "100", "101", "200", "210", "NA", "NA"]
变异方法以及扩展 MutableCollection:
The mutating method as well extending MutableCollection:
public extension MutableCollection where Element: StringProtocol, Self: RandomAccessCollection {
mutating func localizedStandardSort(ascending: Bool = true) {
let result: ComparisonResult = ascending ? .orderedAscending : .orderedDescending
return sort { $0.localizedStandardCompare($1) == result }
}
}
var array = [ "10", "1", "101", "NA", "100", "20", "210", "200", "NA", "7" ]
array.localizedStandardSort()
print(array) // ["1", "7", "10", "20", "100", "101", "200", "210", "NA", "NA"]
如果您需要对数组进行数字排序,可以使用字符串比较方法将选项参数设置为 .numeric
:
If you need to sort your array numerically you can use String compare method setting the options parameter to .numeric
:
public extension Sequence where Element: StringProtocol {
func sortedNumerically(ascending: Bool = true) -> [Element] {
let result: ComparisonResult = ascending ? .orderedAscending : .orderedDescending
return sorted { $0.compare($1, options: .numeric) == result }
}
}
public extension MutableCollection where Element: StringProtocol, Self: RandomAccessCollection {
mutating func sortNumerically(ascending: Bool = true) {
let result: ComparisonResult = ascending ? .orderedAscending : .orderedDescending
return sort { $0.compare($1, options: .numeric) == result }
}
}
var numbers = ["1.5","0.5","1"]
let sortedNumbers = numbers.sortedNumerically()
print(sortedNumbers) // ["0.5", "1", "1.5"]
print(numbers) // ["1.5","0.5","1"]
// mutating the original collection
numbers.sortNumerically(ascending: false)
print(numbers) // "["1.5", "1", "0.5"]\n"
要按其属性之一对自定义类/结构进行排序:
To sort a custom class/structure by one of its properties:
extension MutableCollection where Self: RandomAccessCollection {
public mutating func localizedStandardSort<T: StringProtocol>(_ predicate: (Element) -> T, ascending: Bool = true) {
sort {
predicate($0).localizedStandardCompare(predicate($1)) ==
(ascending ? .orderedAscending : .orderedDescending)
}
}
}
public extension Sequence {
func localizedStandardSorted<T: StringProtocol>(_ predicate: (Element) -> T, ascending: Bool = true) -> [Element] {
sorted {
predicate($0).localizedStandardCompare(predicate($1)) ==
(ascending ? .orderedAscending : .orderedDescending)
}
}
}
public extension Sequence {
func sortedNumerically<T: StringProtocol>(_ predicate: (Element) -> T, ascending: Bool = true) -> [Element] {
let result: ComparisonResult = ascending ? .orderedAscending : .orderedDescending
return sorted { predicate($0).compare(predicate($1), options: .numeric) == result }
}
}
public extension MutableCollection where Element: StringProtocol, Self: RandomAccessCollection {
mutating func sortNumerically<T: StringProtocol>(_ predicate: (Element) -> T, ascending: Bool = true) {
let result: ComparisonResult = ascending ? .orderedAscending : .orderedDescending
return sort { predicate($0).compare(predicate($1), options: .numeric) == result }
}
}
游乐场测试
Playground testing
struct Person {
let name: String
let age : Int
}
extension Person : CustomStringConvertible {
var description: String { "name: \(name), age: \(age)" }
}
let people: [Person] = [.init(name: "Éd Sheeran", age: 26),
.init(name: "phil Collins", age: 66),
.init(name: "Shakira", age: 40),
.init(name: "rihanna", age: 25),
.init(name: "Bono", age: 57)]
let sorted = people.localizedStandardSorted(\.name)
print(sorted) // [name: Bono, age: 57, name: Éd Sheeran, age: 26, name: phil Collins, age: 66, name: rihanna, age: 25, name: Shakira, age: 40]
这篇关于Swift用字符串和数字对数组进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!