2015-10-23 14 views
6

Come posso dividere lo String dato in Swift in gruppi con una determinata lunghezza, leggendo da destra a sinistra?Dividi stringa in gruppi con lunghezza specifica

Ad esempio, ho stringa 123456789 e gruppo lunghezza 3. La stringa deve essere divisa in 3 gruppi: 123, 456, 789. String 1234567 sarà diviso in 1, 234, 567

Quindi, si può scrivere qualche bel codice Swift:

func splitedString(string: String, length: Int) -> [String] { 

} 

funzione BTW provato split(), ma se ho capito bene funziona solo con la ricerca di qualche simbolo

+0

Qual è l'obiettivo e quali sono i vincoli? Stai cercando di formattare le rappresentazioni dei numeri, es: "10000" diventa "10 000", per caso? – Moritz

+0

@EricD. No, 'NSNumberFormatter' non è il mio caso. Voglio solo sapere, posso realizzare questa funzionalità con la funzione 'split()' o qualche altra bella soluzione. – katleta3000

+0

Nota esattamente la stessa (perché il * ultimo * blocco viene troncato, non il primo come nell'esempio), ma potrebbe essere il server come punto di partenza: stackoverflow.com/a/28560013/1187415. –

risposta

2

Giusto per aggiungere il mio ingresso a questo contest molto affollata (SwiftStub):

func splitedString(string: String, length: Int) -> [String] { 
    var result = [String]() 

    for var i = 0; i < string.characters.count; i += length { 
     let endIndex = string.endIndex.advancedBy(-i) 
     let startIndex = endIndex.advancedBy(-length, limit: string.startIndex) 
     result.append(string[startIndex..<endIndex]) 
    } 

    return result.reverse() 
} 

Oppure, se vi sentite funzionale-y:

func splitedString2(string: String, length: Int) -> [String] { 
    return 0.stride(to: string.characters.count, by: length) 
     .reverse() 
     .map { 
      i -> String in 
      let endIndex = string.endIndex.advancedBy(-i) 
      let startIndex = endIndex.advancedBy(-length, limit: string.startIndex) 
      return string[startIndex..<endIndex] 
     } 
} 
+0

@thanks, mi piace la tua variante) – katleta3000

1

Questo è quello che mi è venuto fuori dalla cima della mia testa. Scommetto che c'è un modo migliore per farlo, quindi ti incoraggio a continuare a provare.

func splitedString(string: String, length: Int) -> [String] { 
    var groups = [String]() 
    var currentGroup = "" 
    for index in string.startIndex..<string.endIndex { 
     currentGroup.append(string[index]) 
     if currentGroup.characters.count == 3 { 
      groups.append(currentGroup) 
      currentGroup = "" 
     } 
    } 

    if currentGroup.characters.count > 0 { 
     groups.append(currentGroup) 
    } 

    return groups 
} 

Qui erano le mie prove

let firstString = "123456789" 
let groups = splitedString(firstString, length: 3) 
// Returned ["123", "456", "789"] 

let secondString = "1234567" 
let moreGroups = splitedString(secondString, length: 3) 
// Returned ["123", "456", "7"] 
+0

Questo tronca l'ultimo blocco, non il primo come nell'esempio nella domanda. –

+0

Grazie, è possibile usare la funzione 'split()'? – katleta3000

+0

Ho cercato di usarlo ma senza fortuna al momento. – aahrens

0

ho fatto qualcosa di simile, non ha potuto creare qualcosa di più bello, ma il suo risultato corrisponde alla domanda:

func splitedString(string: String, lenght: Int) -> [String] { 
    var result = [String](), count = 0, line = "" 
    for c in string.characters.reverse() { 
     count++; line.append(c) 
     if count == lenght {count = 0; result.append(String(line.characters.reverse())); line = ""} 
    } 
    if !line.isEmpty {result.append(String(line.characters.reverse()))} 
    return result.reverse() 
} 
1

Ecco una versione utilizzando NSRegularExpressions

func splitedString(string: String, length: Int) -> [String] { 
    var groups = [String]() 
    let regexString = "(\\d{1,\(length)})" 
    do { 
     let regex = try NSRegularExpression(pattern: regexString, options: .CaseInsensitive) 
     let matches = regex.matchesInString(string, options: .ReportCompletion, range: NSMakeRange(0, string.characters.count)) 
     let nsstring = string as NSString 
     matches.forEach { 
      let group = nsstring.substringWithRange($0.range) as String 
      groups.append(group) 
     } 
    } catch let error as NSError { 
     print("Bad Regex Format = \(error)") 
    } 

    return groups 
} 
1

Ecco un'altra versione con Programmazione funzionale.

extension String{ 
    func splitedString(length: Int) -> [String]{ 
     guard length > 0 else { return [] } 
     let range = 0..<((characters.count+length-1)/length) 
     let indices = range.map{ length*$0..<min(length*($0+1),characters.count) } 
     return indices 
       .map{ characters.reverse()[$0.startIndex..<$0.endIndex] } 
       .map(String.init) 
    } 
} 

"1234567890".splitedString(3) 
0

C'è probabilmente una soluzione più elegante, ma questo funziona:

func splitedString(string: String, length: Int) -> [String] { 
    let string = Array(string.characters) 
    let firstGroupLength = string.count % length 
    var result: [String] = [] 
    var group = "" 

    if firstGroupLength > 0 { 
     for i in 0..<firstGroupLength { 
      group.append(string[i]) 
     } 
     result.append(String(group)) 
     group = "" 
    } 

    for i in firstGroupLength..<string.count { 
     group.append(string[i]) 
     if group.characters.count == length { 
      result.append(group) 
      group = "" 
     } 
    } 
    return result 
} 

splitedString("abcdefg", length: 2) // ["a", "bc", "de", "fg"] 
splitedString("1234567", length: 3) // ["1", "234", "567"] 
0

Un'altra soluzione che utilizza stringhe:

func splitStringByIntervals(str: String, interval: Int) -> [String] { 

    let st = String(str.characters.reverse()) 
    let length = st.characters.count 
    var groups = [String]() 

    for (var i = 0; i < length; i += interval) { 
     groups.append((st as NSString).substringWithRange(NSRange(location: i, length: min(interval, length - i)))) 
    } 

    return groups.map{ String($0.characters.reverse())}.reverse() 
} 

L'uscita per:

for element in splitStringByIntervals("1234567", interval: 3) { 
    print(element) 
} 

è:

1 
234 
567 
1

Swift 4

Penso che il metodo di estensione sia più utile.

extension String{ 

    public func splitedBy(length: Int) -> [String] { 

     var result = [String]() 

     for i in stride(from: 0, to: self.characters.count, by: length) { 
      let endIndex = self.index(self.endIndex, offsetBy: -i) 
      let startIndex = self.index(endIndex, offsetBy: -length, limitedBy: self.startIndex) ?? self.startIndex 
      result.append(String(self[startIndex..<endIndex])) 
     } 

     return result.reversed() 

    } 

} 

l'esempio di utilizzo:

Swift.debugPrint("123456789".splitedBy(length: 4)) 
// Returned ["1", "2345", "6789"]