Je cherche un moyen rapide de transformer quelque chose comme:
let germany = "DE"
dans
let flag = "\u{1f1e9}\u{1f1ea}"
c'est-à-dire, quel est le mappage de D
sur 1f1e9
et de E
sur 1f1ea
Je cherchais .utf8
pour la chaîne, mais cela renvoie un entier.
FWIW, mon objectif général est de pouvoir prendre un code de pays arbitraire et d’obtenir le drapeau emoji correspondant.
EDIT: Je suis aussi très bien avec juste tenir une table qui fait cette cartographie si elle est disponible quelque part. J'ai cherché sur Google mais je ne l'ai pas trouvé.
Voici une formule générale pour transformer un code pays de deux lettres en drapeau emoji:
func flag(country:String) -> String {
let base = 127397
var usv = String.UnicodeScalarView()
for i in country.utf16 {
usv.append(UnicodeScalar(base + Int(i)))
}
return String(usv)
}
let s = flag("DE")
EDITOoops, inutile de passer par la structure imbriquée String.UnicodeScalarView. Il s'avère que String dispose d'une méthode append
dans ce but précis. Alors:
func flag(country:String) -> String {
let base : UInt32 = 127397
var s = ""
for v in country.unicodeScalars {
s.append(UnicodeScalar(base + v.value))
}
return s
}
EDITOooops à nouveau, dans Swift 3, ils ont perdu la possibilité d’ajouter un UnicodeScalar à une chaîne et ils ont rendu l’initialiseur UnicodeScalar disponible (Xcode 8 seed 6).
func flag(country:String) -> String {
let base : UInt32 = 127397
var s = ""
for v in country.unicodeScalars {
s.unicodeScalars.append(UnicodeScalar(base + v.value)!)
}
return String(s)
}
Si vous recherchez une solution dans ObjectiveC, voici une catégorie pratique:
@interface NSLocale (RREmoji)
+ (NSString *)emojiFlagForISOCountryCode:(NSString *)countryCode;
@end
@implementation NSLocale (RREmoji)
+ (NSString *)emojiFlagForISOCountryCode:(NSString *)countryCode {
NSAssert(countryCode.length == 2, @"Expecting ISO country code");
int base = 127462 -65;
wchar_t bytes[2] = {
base +[countryCode characterAtIndex:0],
base +[countryCode characterAtIndex:1]
};
return [[NSString alloc] initWithBytes:bytes
length:countryCode.length *sizeof(wchar_t)
encoding:NSUTF32LittleEndianStringEncoding];
}
@end
tester:
for ( NSString *countryCode in [NSLocale ISOCountryCodes] ) {
NSLog(@"%@ - %@", [NSLocale emojiFlagForISOCountryCode:countryCode], countryCode);
}
sortie:???????? - UN D???????? - AE ???????? - UN F???????? - AG ???????? - AI ...
Deux optimisations de la réponse de matt.
Voici le code.
func flag(from country:String) -> String {
let base : UInt32 = 127397
var s = ""
for v in country.uppercased().unicodeScalars {
s.unicodeScalars.append(UnicodeScalar(base + v.value)!)
}
return s
}
Pour donner plus de perspicacité dans la réponse mate
Swift 2 version
public static func flag(countryCode: String) -> Character {
let base = UnicodeScalar("????").value - UnicodeScalar("A").value
let string = countryCode.uppercaseString.unicodeScalars.reduce("") {
var string = $0
string.append(UnicodeScalar(base + $1.value))
return string
}
return Character(string)
}
Version Swift 3, extraite de https://github.com/onmyway133/Smile/blob/master/Sources/Smile.Swift#L52
public func emoji(countryCode: String) -> Character {
let base = UnicodeScalar("????").value - UnicodeScalar("A").value
var string = ""
countryCode.uppercased().unicodeScalars.forEach {
if let scala = UnicodeScalar(base + $0.value) {
string.append(String(describing: scala))
}
}
return Character(string)
}
Pour une approche plus fonctionnelle, n'utilisant pas de variables mutables, utilisez ceci:
private func flag(country: String) -> String {
let base: UInt32 = 127397
return country.unicodeScalars
.flatMap({ UnicodeScalar(base + $0.value) })
|> String.UnicodeScalarView.init
|> String.init
}
Où l'opérateur |>
est l'opérateur d'application de la fonction, fonctionnant comme un "tuyau" pour un ordre de lecture plus naturel: nous prenons les scalaires, les mappons dans de nouveaux scalaires, transformons cela en vue, et cela en chaîne.
C'est défini comme suit:
infix operator |> : MultiplicationPrecedence
func |> <T, U>(left: T, right: (T) -> U) -> U {
return right(left)
}
Sans opérateurs personnalisés, on peut toujours se passer d'état mutable, comme ceci:
private func flag(country: String) -> String {
let base: UInt32 = 127397
return String(String.UnicodeScalarView(
country.unicodeScalars.flatMap({ UnicodeScalar(base + $0.value) })
))
}
Mais à mon humble avis, cela se lit un peu "en arrière", car le flux naturel des opérations ne lit ni en entrée, ni en entrée, mais un peu des deux.
Comme d'habitude, @matt a la bonne réponse.
Sa solution pour Swift3 en utilisant flatMap
et joined
:
func flag(country: String) -> String {
let base: UInt32 = 127397
return country.unicodeScalars.flatMap { String.init(UnicodeScalar(base + $0.value)!) }.joined()
}
Ce que flatMap
fait: Il mappe chaque unicodeScalar
de country
avec la base dans une nouvelle String
qui est joined
au résultat.