2016-06-16 1 views
3

Jusqu'à maintenant (Swift 2.2) J'ai été heureux d'utiliser le code de this answer - c'est swifty, c'est élégant, ça a fonctionné comme un rêve.Swift 3: Trier (anciennement trier en place) tableau par descripteurs de tri

extension MutableCollectionType where Index : RandomAccessIndexType, Generator.Element : AnyObject { 
    /// Sort `self` in-place using criteria stored in a NSSortDescriptors array 
    public mutating func sortInPlace(sortDescriptors theSortDescs: [NSSortDescriptor]) { 
     sortInPlace { 
      for sortDesc in theSortDescs { 
       switch sortDesc.compareObject($0, toObject: $1) { 
       case .OrderedAscending: return true 
       case .OrderedDescending: return false 
       case .OrderedSame: continue 
       } 
      } 
      return false 
     } 
    } 
} 

extension SequenceType where Generator.Element : AnyObject { 
    /// Return an `Array` containing the sorted elements of `source` 
    /// using criteria stored in a NSSortDescriptors array. 
    @warn_unused_result 
    public func sort(sortDescriptors theSortDescs: [NSSortDescriptor]) -> [Self.Generator.Element] { 
     return sort { 
      for sortDesc in theSortDescs { 
       switch sortDesc.compareObject($0, toObject: $1) { 
       case .OrderedAscending: return true 
       case .OrderedDescending: return false 
       case .OrderedSame: continue 
       } 
      } 
      return false 
     } 
    } 
} 

Swift 3 change tout.

Utilisation de l'outil de migration de code et Proposal SE- 0006-sort() => sorted(), sortInPlace() => sort() - j'été aussi loin que

extension MutableCollection where Index : Strideable, Iterator.Element : AnyObject { 
    /// Sort `self` in-place using criteria stored in a NSSortDescriptors array 
    public mutating func sort(sortDescriptors theSortDescs: [SortDescriptor]) { 
     sort { 
      for sortDesc in theSortDescs { 
       switch sortDesc.compare($0, to: $1) { 
       case .orderedAscending: return true 
       case .orderedDescending: return false 
       case .orderedSame: continue 
       } 
      } 
      return false 
     } 
    } 
} 

extension Sequence where Iterator.Element : AnyObject { 
    /// Return an `Array` containing the sorted elements of `source` 
    /// using criteria stored in a NSSortDescriptors array. 

    public func sorted(sortDescriptors theSortDescs: [SortDescriptor]) -> [Self.Iterator.Element] { 
     return sorted { 
      for sortDesc in theSortDescs { 
       switch sortDesc.compare($0, to: $1) { 
       case .orderedAscending: return true 
       case .orderedDescending: return false 
       case .orderedSame: continue 
       } 
      } 
      return false 
     } 
    } 
} 

La fonction « tri » compile [et travaille] sans problème. Pour 'sort' je reçois une erreur sur la ligne qui dit 'sort': "Impossible de convertir la valeur de type '(_, _) -> _' en type d'argument attendu '[SortDescriptor]'" qui m'a complètement déconcerté: I Je ne comprends pas où le compilateur essaie de convertir quoi que ce soit puisque je passe dans un tableau de SortDescriptors, qui devrait être un tableau de SortDescriptors.

Habituellement, ce type d'erreur signifie que vous manipulez des options où vous devriez avoir des valeurs définies, mais puisqu'il s'agit d'un argument de fonction - et semble fonctionner sans accroc dans func sorted - tout ce que je peux lire est que 'quelque chose ne va pas'. Pour l'instant, je n'ai aucune idée de ce qu'est quelque chose, et puisque nous en sommes aux premières étapes de la version bêta, il n'y a aucune documentation du tout.

Pour contourner ce problème, j'ai supprimé le genre de fonction (anciennement tri en place) de mon code et remplacé par une danse de

laisser sortedArray = oldArray (tri [...] oldArray = sortedArray

mais je serais vraiment reconnaissant si je pouvais obtenir mon genre en place la fonctionnalité de retour

+0

Pourquoi ne pas simplement quelque chose le long des goûts de '(tableau en tant que NSArray) .sortedArray (en utilisant: sortDescriptors)'? Il n'y a rien de mal à faire la transition vers les types de fondation où ils fournissent la fonctionnalité dont vous avez besoin. – rickster

+0

a) Je préfère éviter le pontage, car il est possible que le pont sans frais disparaisse à un moment donné. (Nous voyons déjà cette tendance). Aussi, b) J'ai une méthode qui fonctionnera, donc ce n'est pas urgent; mais je voudrais comprendre ce qui se passe ici - il me manque quelque chose, et je ne peux pas le voir par moi-même. –

+0

Pouvez-vous donner un exemple de la façon dont vous avez utilisé ces méthodes dans Swift 2.2? –

Répondre

1

Comparer les méthodes disponibles dans Swift 2.2.

enter image description here

avec les méthodes Swift 3:

enter image description here

Notez que Swift 3 ne dispose pas d'une méthode sort qui accepte une fermeture isOrderedBefore.

C'est pourquoi votre fonction ne sera pas compilée. Cela ressemble à un bug, donc je l'ai signalé comme bug 26857748 sur bugreport.apple.com.

+0

Où avez-vous trouvé ces méthodes? Dans Xcode 8, j'obtiens seulement la variante isOrderedBefore dans l'achèvement du code. (tri et tri dans les aires de jeux, iOS et MacOS, triés uniquement dans le projet MacOS). La variante triée (sortDescriptors :) est disponible pour NSArray dans un projet MacOS, mais pas dans un fichier playground. –

+0

Ce qui précède provient d'un fichier de terrain iOS dans Xcode 8. –

+0

Apple dit que la méthode est maintenant 'sort (by:)' mais je ne trouve pas cette méthode sur MutableCollection. Il semble seulement exister sur EmptyCollection et CollectionOfOne . –

0

laisser sortedArray = users.sorted {$ 0.name < $ 1.name}

+0

cela ne fonctionne pas avec swift 3. –

+0

L'OP veut trier en place, pas créer un nouveau tableau. –

0

Utilisez RandomAccessCollection protocole

extension MutableCollection where Self : RandomAccessCollection { 
    /// Sort `self` in-place using criteria stored in a NSSortDescriptors array 
    public mutating func sort(sortDescriptors theSortDescs: [NSSortDescriptor]) { 
     sort { by: 
      for sortDesc in theSortDescs { 
       switch sortDesc.compare($0, to: $1) { 
       case .orderedAscending: return true 
       case .orderedDescending: return false 
       case .orderedSame: continue 
       } 
      } 
      return false 
     } 
    } 
} 
0

Dans Swift 3,0

let sortedCapitalArray = yourArray.sorted {($0 as AnyObject).localizedCaseInsensitiveCompare(($1 as AnyObject)as! String) == ComparisonResult.orderedAscending}