J'ai une chaîne qui contient des chiffres binaires. Comment le séparer en paires de chiffres?
Supposons que la chaîne est:
let x = "11231245"
Je veux ajouter un séparateur tel que ":" (c'est-à-dire deux points) après chaque 2 caractères.
Je voudrais que la sortie soit:
"11:23:12:45"
Comment pourrais-je faire cela à Swift?
Swift 4.2 • Xcode 10
extension Collection {
var pairs: [SubSequence] {
var startIndex = self.startIndex
let count = self.count
let n = count/2 + (count % 2 == 0 ? 0 : 1)
return (0..<n).map { _ in
let endIndex = index(startIndex, offsetBy: 2, limitedBy: self.endIndex) ?? self.endIndex
defer { startIndex = endIndex }
return self[startIndex..<endIndex]
}
}
}
extension StringProtocol where Self: RangeReplaceableCollection {
mutating func insert(separator: Self, every n: Int) {
for index in indices.reversed() where index != startIndex &&
distance(from: startIndex, to: index) % n == 0 {
insert(contentsOf: separator, at: index)
}
}
func inserting(separator: Self, every n: Int) -> Self {
var string = self
string.insert(separator: separator, every: n)
return string
}
}
Essais
let str = "112312451"
let final = str.pairs.joined(separator: ":")
print(final) // "11:23:12:45:1"
let final2 = str.inserting(separator: ":", every: 2)
print(final2) // "11:23:12:45:1\n"
var str2 = "112312451"
str2.insert(separator: ":", every: 2)
print(str2) // "11:23:12:45:1\n"
var str3 = "112312451"
str3.insert(separator: ":", every: 3)
print(str3) // "112:312:451\n"
var str4 = "112312451"
str4.insert(separator: ":", every: 4)
print(str4) // "1123:1245:1\n"
Je vais aller pour cette solution compacte (dans Swift 4):
let s = "11231245"
let r = String(s.enumerated().map { $0 > 0 && $0 % 2 == 0 ? [":", $1] : [$1]}.joined())
Vous pouvez créer une extension et paramétrer la foulée et le séparateur afin de pouvoir l’utiliser pour chaque valeur de votre choix (dans mon cas, je l’utilise pour dump des données hexadécimales 32 bits exploitées dans l’espace):
extension String {
func separate(every stride: Int = 4, with separator: Character = " ") -> String {
return String(enumerated().map { $0 > 0 && $0 % stride == 0 ? [separator, $1] : [$1]}.joined())
}
}
Dans votre cas, cela donne les résultats suivants:
let x = "11231245"
print (x.separate(every:2, with: ":")
$ 11:23:12:45
let y = String(
x.characters.enumerate().map() {
$0.index % 2 == 0 ? [$0.element] : [$0.element, ":"]
}.flatten()
)
Ma tentative à ce code serait:
func insert(seperator: String, afterEveryXChars: Int, intoString: String) -> String {
var output = ""
intoString.characters.enumerate().forEach { index, c in
if index % afterEveryXChars == 0 && index > 0 {
output += seperator
}
output.append(c)
}
return output
}
insert(":", afterEveryXChars: 2, intoString: "11231245")
Quelles sorties
11: 23: 12: 45
C'est mon code dans Swift 4
let x = "11231245"
var newText = String()
for (index, character) in x.enumerated() {
if index != 0 && index % 2 == 0 {
newText.append(":")
}
newText.append(String(character))
}
print(newText)
Sorties 11: 23: 12: 45
extension String{
func separate(every: Int) -> [String] {
return stride(from: 0, to: count, by: every).map {
let ix0 = index(startIndex, offsetBy: $0);
let ix1 = index(after:ix0);
if ix1 < endIndex {
return String(self[ix0...ix1]);
}else{
return String(self[ix0..<endIndex]);
}
}
}
/// ou O(1) implémentation (sans nombre)
func separate(every: Int) -> [String] {
var parts:[String] = [];
var ix1 = startIndex;
while ix1 < endIndex {
let ix0 = ix1;
var n = 0;
while ix1 < endIndex && n < every {
ix1 = index(after: ix1);
n += 1;
}
parts.append(String(self[ix0..<ix1]));
}
return parts;
}
"asdf234sdf".separate(every: 2).joined(separator: ":");
Une simple extension de chaîne qui n'exige pas que la chaîne d'origine soit un multiple de la taille de l'étape (incrément):
extension String {
func inserted(_ newElement: Character,atEach increment:Int)->String {
var newStr = self
for indx in stride(from: increment, to: newStr.count, by: increment).reversed() {
let index = String.Index(encodedOffset: indx)
newStr.insert(newElement, at: index)
}
return newStr
}
}