2014-11-20 21 views
6

Aşağıda gösterildiği gibi 1 değerine göre sıralama yapmak için kodum var, ancak birden çok değer kullanarak nasıl sıralanacağımı merak ediyorum. Setine göre sıralamak istiyorum ve sonra bazındaString.Bir dizi yapıyı birden çok değere göre nasıl sıralarım?

biri bir tam sayıdır ve kimse bu durumda bir dizedir. Tamsayı bir dizgeye dönüştürmeyi ve daha sonra bunları birleştirmeyi düşünmüştüm, ama daha iyi bir yol olmalı diye düşündüm çünkü gelecekte sıralamak için 2 tane tam sayıya sahip olabilirim.

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)") 
} 

cevap

9

Ben Swift henüz yetkin değilim, ama sıralama is çoklu kriterler temel fikir: set değerleri aynı, aksi takdirde kullanım olsaydı

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) 
} 
+0

Kodumu düzeltmek için teşekkürler @Aaron. – Cyrille

4

Sen someString karşılaştırmak istiyorsunuz mevcut karşılaştırması:

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 
    } 
} 
+0

Bu böyle yapar. Teşekkürler! –

+0

bu işe yarıyor! teşekkürler – Led

6

Hatta önceki cevaplar talep durumunda tamamen normal olmasına rağmen, ben daha genel bir yaklaşım f koymak istiyorum ya o: istenen gibi buradan


infix operator <=> { 
associativity none 
precedence 130 
} 
func <=> &ltT: Comparable>(lhs: T, rhs: T) -> NSComparisonResult { 
    return lhs < rhs ? .OrderedAscending : lhs == rhs ? .OrderedSame : .OrderedDescending 
} 
private func _sortedLexicographically&ltS: 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&ltS: 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) 
    } 
} 

bir sıralama yapmak oldukça kolay:


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 }]) 

türü için karşılaştırma bu tür tip kendisine içkin ise yerine bir yer-olmanın sadece ihtiyacınız sıralama, daha stdlib benzeri bir yaklaşım takip etmek ve yerine Comparable uzanan edebilirsiniz:


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) 

biryapıyor başka bir olası yaklaşım olacaktı Comparable alanları ve hangi öncelik onlar var, ama Swift tipik tip güvenliğini korurken maalesef, 2.0 olarak Swift desteklenmeyen variadic jenerikler, kullanmadan bunu yapmak için bir yol düşünemiyorum hangi diyorprotokolü kodu.

+2

Bu doğru yaklaşım, IMHO. Bir yapı tanımlayacaksanız ve bunu karşılaştırabilmek istiyorsanız, o zaman sipariş vermek için – Abizern

+0

'u tanımlayan yapıyı kabul ediyorum. Ama yine de alternatif bir sıralama düzeni göstermek istediğiniz durumlar olabilir ve bunu mümkün kılarsınız. Dedikleri gibi: YMMV – DeFrenZ

+0

Bu sorunu çözmek için hızlı özel işleçlerin yanı sıra jeneriklerin kullanımını göstermiş olması için ekstra puan verilmelidir! Bravo! – quickthyme

İlgili konular