Swift string: добавить 0 после десятичного разделителя

Мне нужно добавить 0, 1 или 2 0 в строку, в зависимости от ее десятичного разделителя, чтобы

  • «100», «100». и "100.0" становится "100.00"
  • «100,8» становится «100,80».
  • «100,85» остается без изменений.

Я мог бы найти десятичный разделитель и проверить расстояние до конца endIndex строки, но есть ли более простой способ сделать это?

NumberFormatter делает это, но фактическая строка, которая у меня есть, не является простым числом, которое можно пройти через форматтер.

Например:

let amount = "123,456,789"

тогда форматированная сумма должна быть "123 456 789,00".

предположение:

данная строка имеет не более одного десятичного разделителя с не более чем двумя десятичными знаками

Таким образом, не может быть такой строки: "123.4.4.5"

Также хочу использовать десятичный разделитель из NumberFormatter().decimalSeparator

@rmaddy Да, но фактическая строка не является простым числом, это число с чем-то другим.

hzxu 10.09.2018 09:00

Вы тоже можете привести пример?

Rakesha Shastri 10.09.2018 09:01

Вам необходимо разместить соответствующий код. Покажите, что у вас действительно есть и что вам действительно нужно, помимо того, что вы пробовали, и с какими проблемами вы столкнулись.

rmaddy 10.09.2018 09:02

Что, если строка будет «123,4567», «1,234,567» или «Цена: 1 евро за»?

Martin R 10.09.2018 09:07

Кроме того, хотите ли вы сделать это с учетом локали или вы всегда используете "." как десятичный разделитель?

Nikolai Ruhe 10.09.2018 09:08
stackoverflow.com/questions/29782982/…
Leo Dabus 10.09.2018 09:12
1
6
119
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы можете передать строку через средство форматирования десятичных чисел, чтобы получить базовое число, а затем обратно через средство форматирования, чтобы получить отформатированную строку:

let amount = "123,456,789"
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.maximumFractionDigits = 2
formatter.minimumFractionDigits = 2
let number = formatter.number(from: amount)
let newAmountString = formatter.string(from: number!)  //"123,456,789.00"

(Вы должны убедиться, что номер не является nil, прежде чем принудительно развернуть его с помощью if let или guard)

Вы можете обернуть это функцией:

func zeroPadding(toString: String) -> String? {
    let formatter = NumberFormatter()
    formatter.numberStyle = .decimal
    formatter.maximumFractionDigits = 2
    formatter.minimumFractionDigits = 2
    guard let number = formatter.number(from: toString) else {
        return nil
    }
    return formatter.string(from: number)
}

Вот несколько тестовых примеров:

zeroPadding(toString: "123,456,789")         //"123,456,789.00"
zeroPadding(toString: "123,456,789.0")       //"123,456,789.00"
zeroPadding(toString: "123,456,789.10")      //"123,456,789.10"
zeroPadding(toString: "123,456,789.123")     //"123,456,789.12"
zeroPadding(toString: "123.4567")            //"123.46"
zeroPadding(toString: "Price: 1€ for a 💩")  //nil

Или определите его как расширение на Нить:

extension String {
    func withZeroPadding() -> String? {
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal
        formatter.maximumFractionDigits = 2
        formatter.minimumFractionDigits = 2
        guard let number = formatter.number(from: self) else {
            return nil
        }
        return formatter.string(from: number)
    }
}

И используйте это так:

"123.4.4.5".withZeroPadding()    //nil 
"12.".withZeroPadding()          //"12.00"
"123,456,789".withZeroPadding()  //"123,456,789.00"

Это следующий фрагмент кода, который я протестировал на Playground. Его можно реализовать более эффективно, но пока он работает.

//let amount = "123,456,789.545222323"
//let amount = "123,456,789."
let amount = "123,456,789"
let removeSpaces = amount.replacingOccurrences(of: " ", with: "")


if removeSpaces.count > 0
{
let arrSTR = removeSpaces.components(separatedBy: ".")
if  arrSTR.count > 1
{
    var strAfterDecimal = arrSTR[1]
    if strAfterDecimal.count >= 2
    {
        strAfterDecimal = strAfterDecimal[0..<2]
    }else if strAfterDecimal.count != 0
    {
        strAfterDecimal = "\(strAfterDecimal)0"
    }else
    {
        strAfterDecimal = "00"
    }
    let finalSTR = String("\(arrSTR[0]).\(strAfterDecimal)")
    print("Final with Decimal - \(finalSTR)")
}else
{
    let finalSTR = String(arrSTR[0] + ".00")
    print("Final without Decimal - \(finalSTR)")
}
}

extension String {
subscript(_ range: CountableRange<Int>) -> String {
    let idx1 = index(startIndex, offsetBy: max(0, range.lowerBound))
    let idx2 = index(startIndex, offsetBy: min(self.count, range.upperBound))
    return String(self[idx1..<idx2])
}
}

Другие вопросы по теме