donné [INT?], Besoin de construire une chaîne à partir de celui-ci.
Cet extrait de code fonctionne p> mais je n'aime pas plattmap Code> suivi de
mappe code>. Y a-t-il une meilleure solution? P> P>
6 Réponses :
Si vous n'aimez pas le avec cette p> platmap code> et la carte
ensemble, vous pouvez remplacer ce
let result = [optionalInt1, optionalInt2].flatMap {
guard let num = $0 else { return nil }
return String(num)
}.joined(separator: ",")
Belle prise! J'ai oublié .description code> essayer de faire fonctionner les choses avec
String (décrivant :) code>,
chaîne () code>
Notez que l'équipe SWIFT vous décourage d'accéder directement à la propriété code> code> (dernier paragraphe de la vue d'ensemble Dans les docs ) - Bien que j'avoue que cela permet d'appeler un joli appel.
@Hamish: Je ne le savais pas. Merci beaucoup pour l'information.
Voici une autre approche:
[optionalInt1, optionalInt2].flatMap { $0.map(String.init) }
Cette solution fonctionnera également lorsque le type générique de la matrice ne correspond pas à CustomStringConversible code> ou ne dispose pas d'une propriété code> (code>.
@Yakivkovalskiy Dans ce cas, il est très évident que 0 $ code> est
.Some (...) code> si la 2e cible conditionnelle de l'opérateur ternaire est entrée; Un cas particulier où nous pouvons vraiment utiliser
! code> en toute sécurité et en même temps, sémantiquement, que nous savons ce que nous faisons.
@Yakivkovalskiy Le débit forcé n'est pas nécessairement mauvais. C'est bien utilisé et maltraité, mais c'est parfaitement justifiable dans un cas comme celui-ci
@Alexander Vous avez peut-être raison. À mon avis, il ne faut plus jamais utiliser la force de la force du code SWIFT, mais ce sujet est trop controversé pour discuter ici.
@Yakivkovalskiy jamais i> est une déclaration assez forte, il y a plusieurs endroits où il n'y a vraiment aucun autre choix, tel que pour les définitions de fermeture récursives
Flatmap code> a été remplacé par
compactmap code>.
Vous pouvez utiliser le aussi, si vous n'enveloppez pas les fermetures de fin (de mappe code> méthode de
dans un en option code>
Flatmap CODE> Fermeture appliquée sur le tableau, faisant appel au fait que le premier retournera
nil code> sans entrer dans le fermeture fournie dans le cas où la facultative elle-même est
nil code>:
platmap code>,
mappe code>) dans la paranthèse et utilise en outre le fait que la référence d'initialisateur
string.init code> sera (dans ce cas) (dans ce cas) non ambigueusement à la correction
Chaîne code> initialiseur (tel qu'utilisé ci-dessus), un
plat de colonne code> et
carte code> ne doit pas avoir l'air "gonflé", et est également une approche entièrement valide ici (la Enchaîné
Flatmap CODE> et
MAP CODE> Tenez également la valeur pour la sémantique). P>
let unwrappedStrings = [optionalInt1, optionalInt2]
.flatMap{ $0 }.map(String.init)
Mais j'essaie d'éviter l'utilisation de mappe code> et
flatmap code> ici parce que la boucle via la matrice ne peut pas être bonne.
@Yakivkovalskiy Notez que la première solution ci-dessus utilise la carte code> Fonctionnement du type facultatif i> (qui est un seul appel à une méthode d'instance de l'élément optionnel), pas du tableau , donc il n'y aura qu'un seul passage sur le tableau dans celui-là. La première méthode ci-dessus est presque équivalente à @ Solution d'Alexandre ci-dessous . Néanmoins, un platmap code> et
et
est toujours
o (n) code>, et je ne vois pas comment cela pourrait jamais être " ne peut pas être bon » i> sauf si vous travaillez avec une application HPC extrêmement lourde. Sinon, mettez également la mise au point sur la sémantique.
@Yakivkovalsky Si vous souhaitez éviter la boucle répétée, utilisez .lazy code>. Par exemple.
Array.Map (fn1) .Map (FN2) CODE> ne lira que les éléments une fois, appliquant chaque fonction successivement, sans copier / stocker des résultats intermédiaires dans des tableaux intermédiaires.
Éviter complètement la colonne et la carte. Cependant, créer un var.
let optionalInt1: Int? = 1 let optionalInt2: Int? = nil let optionalInts = [optionalInt1, optionalInt2] var strings = [String]() for optInt in optionalInts { if let integer = optInt { strings.append(String(integer)) } } let string = strings.joined(separator: ",")
"Éviter complètement la colonne et la carte" ne fais pas ça.
@ Alexander-Reinstatetemonica puis-je savoir pourquoi?
Toute votre pour code> La boucle est juste une façon vraiment longue de dire
platmap code> (maintenant appelé
compactmap code>, pour cette variante). Pourquoi réinventer la roue?
Les autres réponses utilisent en utilisant sortie: p> Flatmap CODE> pour éliminer les éléments
nil code> et nécessiter un appel sur
joint () code> pour combiner les éléments et ajouter les virgules .
joint () code> pour ajouter les virgules est bien sûr une seconde passe à travers la
déployer. Voici un moyen d'utiliser
Réduire code> pour le faire en une seule passe: p>
let result = arr.reduce(into: "") { (string, elem) in
guard let elem = elem else { return }
if string.isEmpty {
string = String(elem)
} else {
string.append(",\(elem)")
}
}
(Je suis conscient que c'est une ancienne réponse) Ceci a O (N ^ 2) Code> La complexité du temps (chaque annexe provoquerait une duplication de chaîne), ce qui n'est pas génial. De plus, étant donné que le code est plus complexe que
platmap code> +
joint (séparateur: "") code>, je vous conseillerais fortement. Voir github.com/amomchilov/blog/blob/master / ...
@ Alexander-réinlevstatetemonica, dans une version de la libération d'un tableau de 10 000 éléments avec 10% nil code> S a pris
0.01 code> secondes à la fois avec ma réponse et votre dernière personne avec
joint (séparateur : ",") code>. Réécriture d'utiliser
Réduire (dans :) CODE> et
ANNEXE CODE> RAN deux fois plus vite. Donc, votre plainte concernant la complexité du code est valide, mais le problème de la rapidité est injustifié.
Mes préoccupations de performance Ces jours-ci sont généralement moins de temps (sauf pour bloquer les appels de réseau, ceux-ci sont toujours un grand non-non), mais plus sur la vie de la batterie. Je ne voudrais pas y mettre beaucoup de temps, mais si c'est trivial (par exemple, mettre un .lazyzy code> avant une chaîne d'appels), je le ferais à l'avant, juste pour garder l'appareil à avoir besoin de utiliser ses noyaux plus élevés et tels.
@ Alexander-réinlevstatemonica, ajout .lazy code> pour faire
laisse résultat = arr.lazy.compactMap {$ 0.map (String.init)} .joind (séparateur: ",") code > ralenti le bas de
0.01068 code> secondes à
0.01469 code> secondes.
@ Alexander-Reinstatetemonica, oui, c'est une version de sortie.
[1,2,3] .flatmap ({String (décrivant: 0)}). Joigné (séparateur: "") P>
// "1 2 3" (Sans guillemets) P>
Cela produit des valeurs de chaîne de en option (1) code> et
nil code>, ce qui n'est presque certainement pas prévu. Et même si c'est était i> destiné, cela vaut probablement une forte réexamen.