我已经有了按1值排序的代码,如下所示,但我想知道如何使用多个值进行排序?我想按set排序,然后按someString排序。
一个是整数,在这种情况下一个是字符串。我曾考虑将整数转换为字符串,然后连接它们,但认为必须有更好的方法,因为我将来可能有2个整数排序。
struct Condition {
var set = 0
var someString = ""
}
var conditions = [Condition]()
conditions.append(Condition(set: 1, someString: "string3"))
conditions.append(Condition(set: 2, someString: "string2"))
conditions.append(Condition(set: 3, someString: "string7"))
conditions.append(Condition(set: 1, someString: "string9"))
conditions.append(Condition(set: 2, someString: "string4"))
conditions.append(Condition(set: 3, someString: "string0"))
conditions.append(Condition(set: 1, someString: "string1"))
conditions.append(Condition(set: 2, someString: "string6"))
// sort
let sorted = conditions.sorted { (lhs: Condition, rhs: Condition) -> Bool in
return (lhs.set) < (rhs.set)
}
// printed sorted conditions
for index in 0...conditions.count-1 {
println("\(sorted[index].set) - \(sorted[index].someString)")
}
答案 0 :(得分:11)
我还不熟悉Swift,但多标准排序的基本思路是:
let sorted = conditions.sorted { (lhs: Condition, rhs: Condition) -> Bool in
if lhs.set == rhs.set {
return lhs.someString < rhs.someString
}
return (lhs.set) < (rhs.set)
}
答案 1 :(得分:6)
尽管之前的答案在所要求的案例中完全没问题,但我想为此提出一个更通用的方法:
infix operator <=> {
associativity none
precedence 130
}
func <=> <T: Comparable>(lhs: T, rhs: T) -> NSComparisonResult {
return lhs < rhs ? .OrderedAscending : lhs == rhs ? .OrderedSame : .OrderedDescending
}
private func _sortedLexicographically<S: SequenceType>(source: S, comparators: [(S.Generator.Element, S.Generator.Element) -> NSComparisonResult]) -> [S.Generator.Element] {
return sorted(source, { lhs, rhs in
for compare in comparators {
switch compare(lhs, rhs) {
case .OrderedAscending: return true
case .OrderedDescending: return false
case .OrderedSame: break
}
}
return false
})
}
public func sortedLexicographically<S: SequenceType>(source: S, comparators: [(S.Generator.Element, S.Generator.Element) -> NSComparisonResult]) -> [S.Generator.Element] {
return _sortedLexicographically(source, comparators)
}
extension Array {
func sortedLexicographically(comparators: [(Element, Element) -> NSComparisonResult]) -> [Element] {
return _sortedLexicographically(self, comparators)
}
}
从这里开始按照要求进行订购非常容易:
struct Foo {
var foo: Int
var bar: Int
var baz: Int
}
let foos = [Foo(foo: 1, bar: 2, baz: 3), Foo(foo: 1, bar: 3, baz: 1), Foo(foo: 0, bar: 4, baz: 2), Foo(foo: 2, bar: 0, baz: 0), Foo(foo: 1, bar: 2, baz: 2)]
let orderedFoos = foos.sortedLexicographically([{ $0.foo <=> $1.foo }, { $0.bar <=> $1.bar }, { $0.baz <=> $1.baz }])
如果该类型的这种比较是类型本身固有的,而不是您需要的一个仅限地点的排序,您可以遵循更像stdlib的方法并扩展Comparable
:
extension Foo: Comparable {}
func == (lhs: Foo, rhs: Foo) -> Bool {
return lhs.foo == rhs.foo && lhs.bar == rhs.bar && lhs.baz == rhs.baz
}
func < (lhs: Foo, rhs: Foo) -> Bool {
let comparators: [(Foo, Foo) -> NSComparisonResult] = [{ $0.foo <=> $1.foo }, { $0.bar <=> $1.bar }, { $0.baz <=> $1.baz }]
for compare in comparators {
switch compare(lhs, rhs) {
case .OrderedAscending: return true
case .OrderedDescending: return false
case .OrderedSame: break
}
}
return false
}
let comparableOrderedFoos = sorted(foos)
还有另一种可能的方法是制定LexicographicallyComparable
协议,说明哪些Comparable
字段以及它们具有哪些优先级,但不幸的是我无法想出一种方法它没有使用可变的泛型,它在Swift 2.0中不受支持,同时保持了Swift代码的典型类型安全性。
答案 2 :(得分:4)
如果someString
值相同,您可以比较set
,否则,请使用您现有的比较:
let sorted = conditions.sorted { (lhs: Condition, rhs: Condition) -> Bool in
if lhs.set == rhs.set {
return lhs.someString < rhs.someString
} else {
return lhs.set < rhs.set
}
}