web-dev-qa-db-fra.com

Comment ajouter un séparateur à une chaîne à chaque N caractères dans swift?

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?

14
Bolo

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"
42
Leo Dabus

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
10
Stéphane de Luca
let y = String(
    x.characters.enumerate().map() {
        $0.index % 2 == 0 ? [$0.element] : [$0.element, ":"]
    }.flatten()
)
7
courteouselk

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

6
luk2302

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

4
Evgeniy
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: ":");
0
john07

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
    }
 }
0
Steig