web-dev-qa-db-fra.com

Tableau de tri dans Swift3

Dans mon code, j'ai une structure comme celle-ci:

struct Object {
    var name: String
    var count: Int

Je suis en train de créer un tableau de 10 objets avec des noms aléatoires et des nombres aléatoires.

Existe-t-il un moyen simple de
a) les trier par ordre alphabétique
b) les trier numériquement par ordre croissant

Fondamentalement, il y aura un tableau comme ceci: [Object1, Object2, Object3]. Chaque objet a un attribut name et count, et je veux que les objets de cette liste soient triés via ces deux attributs.

Solution dans Swift2 (en utilisant cette solution: StackOverflow) :

Object.sort{
        if $0.name != $1.name {
            return $0.name < $1.name
        }
        else {
            //suits are the same
            return $0.count < $1.count
        }
    }

Cependant, cela a été renommé sorted(by: ) dans Swift3, et je ne quitte pas comment faire.

10
Narusan

Si vous souhaitez trier par ordre alphabétique puis numérique, vous pouvez:

var array = ["A2", "B7", "A4", "C3", "A1", "A10"]
array.sort { $0.compare($1, options: .numeric) == .orderedAscending }

Cela produit:

["A1", "A2", "A4", "A10", "B7", "C3"]

J'ai ajouté A10 à votre tableau, car sans lui, un simple tri alphabétique aurait suffi. Mais je suppose que vous vouliez A10 après A4, auquel cas la comparaison numérique fera le travail pour vous.


Vous avez modifié l'exemple pour qu'il soit une structure avec deux propriétés. Dans ce cas, vous pouvez faire quelque chose comme:

struct Foo {
    var name: String
    var count: Int
}

var array = [
    Foo(name:"A", count: 2),
    Foo(name:"B", count: 7),
    Foo(name:"A", count: 7),
    Foo(name:"C", count: 3),
    Foo(name:"A", count: 1),
    Foo(name:"A", count: 10)
]

array.sort { (object1, object2) -> Bool in
    if object1.name == object2.name {
        return object1.count < object2.count
    } else {
        return object1.name < object2.name
    }
}

Ou, plus concis:

array.sort { $0.name == $1.name ? $0.count < $1.count : $0.name < $1.name }

Ou

array.sort { ($0.name, $0.count) < ($1.name, $1.count) }

Remarquez, plutôt que de mettre cette logique dans la fermeture, je ferais en fait Foo conforme à Comparable:

struct Foo {
    var name: String
    var count: Int
}

extension Foo: Equatable {
    static func ==(lhs: Foo, rhs: Foo) -> Bool {
        return (lhs.name, lhs.count) == (rhs.name, rhs.count)
    }
}

extension Foo: Comparable {
    static func <(lhs: Foo, rhs: Foo) -> Bool {
        return (lhs.name, lhs.count) < (rhs.name, rhs.count)
    }
}

Cela maintient la logique de comparaison bien encapsulée dans le type Foo, où elle appartient.

Ensuite, vous pouvez simplement faire ce qui suit pour trier sur place:

var array = ...
array.sort()

Ou, vous pouvez également retourner un nouveau tableau si vous ne souhaitez pas trier l'original en place:

let array = ...
let sortedArray = array.sorted()
25
Rob

Narusan, peut-être que cela vous aidera. Disons que vous avez un tableau avec vos objets struct appelé objArray, alors vous pouvez le classer par le code ci-dessous:

var objArray = [Object]()
objArray.append(Object(name:"Steve", count:0))
objArray.append(Object(name:"Alex", count:1))

objNameSorted = objArray.sorted (by: {$0.name < $1.name})
objNCountSorted = objArray.sorted (by: {$0.count < $1.count})
11
ffabri

Vous pouvez toujours utiliser le raccourci pour sorted:

objNameSorted = objArray.sorted { $0 < $1 }

Bien que moins lisible, il imite de plus près la syntaxe sort.

4
kakubei