2
votes

Comment trier rapidement par un BOOL sans changer l'ordre d'origine dans le tableau principal?

J'ai un tableau de modèles qui a 2 propriétés:

1. Titre (chaîne)

2. selected (Bool)

Je veux les trier en fonction de la propriété selected de manière à ce que cela se fasse par rapport à la séquence du tableau source. Par exemple, si tout est FALSE ou TRUE, il devrait y avoir la même sortie après la commande.

Mais si j'utilise le suivant, cela modifie le tri d'origine après les avoir classés en fonction de cette propriété BOOL.

< pre> XXX

Que dois-je faire pour conserver la séquence d'origine?

MODIFIER 1:

L'ordre de tri du Titre n'apparaît pas dans l'image. Peut-être que le serveur m'envoie 4 objets ayant le titre Z, Y, P, A. Donc, si tout est faux et une fois que je trie, ce devrait être comme Z faux, Y faux, P faux, A faux.


4 commentaires

Est-ce votre véritable code? Vous devriez voir un avertissement du compilateur «La constante 'someArray' est supposée avoir le type '()', ce qui peut être inattendu»


Je viens de placer un prototype


Ce que vous recherchez (apparemment) est une sorte «stable». Dans Swift 5, la méthode sort () se trouve être stable, mais ce n'est pas garanti.


Voir aussi Comment stabiliser le tri d'un tableau en swift? .


4 Réponses :


3
votes

Vous avez besoin de

someArray = array.sorted (by:{ $0.selected && !$1.selected && <#Add more conditions #>})

triés (par ne mute pas le tableau d'origine contrairement au sort

https://developer.apple.com/documentation/swift/array/1688499-sort

https://developer.apple. com / documentation / swift / array / 2296815 triés


3 commentaires

Merci, voir mon EDIT


@RakeshaShastri étant || ou && est selon la logique dont l'op a besoin


@Sh_Khan il y a un if . si cela correspond également aux besoins de l'OP, vous pourriez simplement avoir écrit array.sorted (par: <# What OP needs #>) . Je ne vois aucune différence.



2
votes

Vous devez utiliser la méthode sorted au lieu de sort;

let newArray = array.sorted { $0.selected && !$1.selected }

Fondamentalement, sort trie dans le même tableau, trié renvoie un nouveau tableau, sans changer l'original


0 commentaires

1
votes

Si vous souhaitez conserver la commande que vous recevez d'un serveur, je vous suggérerai de ne pas utiliser la méthode sort ou triée , car ils ne sont pas garantis de conserver l'ordre d'origine pour les clés du même ordre. Je vous recommanderai d'écrire votre propre fonction de tri:

[
  Model(title: "a", selected: true), 
  Model(title: "c", selected: true), 
  Model(title: "a", selected: false), 
  Model(title: "b", selected: false)
 ]

Si vous ne voulez pas créer une extension Comparable à votre modèle (parce que par exemple , vous utilisez un ordre différent de ces modèles à quelques endroits), vous pouvez utiliser la méthode sorted , mais fournir un bloc de tri différent:

struct Model {
    let title:String
    let selected:Bool
}

let array = [ Model(title: "a", selected: true), Model(title: "a", selected: false), Model(title: "b", selected: false), Model(title: "c", selected: true)]

let newArray = array.sorted { (lhs, rhs) -> Bool in
    if lhs.selected == rhs.selected {
        return lhs.title < rhs.title
    }
    return lhs.selected
}
print(newArray)

et l'ordre de tri sera:

struct Model {
    let title:String
    let selected:Bool
}

let array = [ Model(title: "Z", selected: true), Model(title: "Z", selected: false), Model(title: "Y", selected: false), Model(title: "P", selected: false), Model(title: "A", selected: true), Model(title: "A", selected: false)]

extension Array where Element == Model {
    func preserveSorted() -> [Model] {
        var selected:[Model] = []
        var notSelected:[Model] = []

        for model in self {
            if model.selected {
                selected.append(model)
            } else {
                notSelected.append(model)
            }
        }
        var output:[Model] = []
        output.append(contentsOf: selected)
        output.append(contentsOf: notSelected)
        return output
    }
}


var newArray:[Model] = array.preserveSorted()
print(newArray)
/* output:
[
    Model(title: "Z", selected: true),
    Model(title: "A", selected: true),
    Model(title: "Z", selected: false),
    Model(title: "Y", selected: false),
    Model(title: "P", selected: false),
    Model(title: "A", selected: false)
]
*/


2 commentaires

Merci, le titre ne vient pas en image. Peut-être que le serveur m'envoie 4 objets ayant le titre Z, Y, P, A. Donc, si tout est faux et une fois que je trie, cela devrait être comme Z faux, Y faux, P faux, A faux.


@NSPratik J'ai mis à jour ma réponse, pouvez-vous la vérifier?



4
votes

Au lieu de trier, vous pouvez le faire plus efficacement en utilisant une opération de filtrage:

let newArray = array.stableSorted {
   return $0.selected == $1.selected || $0.selected
}

Malheureusement, Array.sorted ne garantit pas un tri stable, vous ne peut pas simplement trier par une propriété et s'attendre à ce que le tri d'origine soit conservé.

Vous pouvez cependant implémenter un tri stable facilement (par exemple https://stackoverflow.com/a/50545761/669586 )

Ensuite, vous pouvez simplement utiliser:

let newArray = array.stableSorted {    
   let numeric1 = $0.selected ? 0 : 1
   let numeric2 = $1.selected ? 0 : 1

   return numeric1 <= numeric2
}

ou p>

let newArray = array.filter { $0.selected } + array.filter { !$0.selected }


0 commentaires