2015-10-23 2 views
6

Как можно разделить заданный String в Swift на группы с заданной длиной, считая справа налево?Разделить строку на группы с определенной длиной

Например, у меня есть строка 123456789 и групповой длина 3. строка должна быть разделена на 3 группы: 123, 456, 789. Строка 1234567 будет разделена на 1, 234, 567

Таким образом, вы можете написать какой-нибудь хороший код Swift:

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

} 

BTW пытался функция split(), но, как я понимаю, что это работает только с поиском какого-то символа

+0

Какова цель и каковы ограничения? Вы пытаетесь форматировать числовые представления, например: «10000» становится «10 000», случайно? – Moritz

+0

@ EricD. Нет, 'NSNumberFormatter' не мой случай. Я просто хочу знать, могу ли я реализовать эту функциональность с помощью функции split() или другого приятного решения. – katleta3000

+0

Обратите внимание на то же самое (поскольку фрагмент * last * усечен, а не первый, как в вашем примере), но может служить сервером в качестве отправной точки: stackoverflow.com/a/28560013/1187415. –

ответ

2

Просто, чтобы добавить свою запись в этом переполненном конкурсе (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() 
} 

Или, если вы чувствуете себя функционально-у:

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, нравится ваш вариант) – katleta3000

1

Это то, что я придумал с головы. Бьюсь об заклад, есть лучший способ сделать это, поэтому я бы посоветовал вам продолжать попытки.

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 
} 

Здесь были мои тесты

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

Это усекает последний кусок, а не первый, как в примере в вопросе. –

+0

Спасибо, можно ли использовать функцию 'split()'? – katleta3000

+0

Я пытался использовать это, но не повезло. – aahrens

0

Я сделал что-то вроде этого, ничего не может создать лучше выглядит, но его результат соответствует вопрос:

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

Вот версия с использованием 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

Вот еще одна версия с функциональным программированием.

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

Там, наверное, более элегантное решение, но это работает:

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

Другое решение с использованием подстрок:

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() 
} 

Выход для:

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

является:

1 
234 
567 
1

Swift 4

Я думаю, что метод расширения более полезен.

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() 

    } 

} 

Пример использования:

Swift.debugPrint("123456789".splitedBy(length: 4)) 
// Returned ["1", "2345", "6789"] 
Смежные вопросы