Swift 2.0 Format 1000's into a friendly K's

断了今生、忘了曾经 提交于 2019-12-30 05:58:02

问题


I'm trying to write a function to present thousands and millions into K's and M's For instance:

1000 = 1k
1100 = 1.1k
15000 = 15k
115000 = 115k
1000000 = 1m

Here is where I got so far:

func formatPoints(num: Int) -> String {
    let newNum = String(num / 1000)
    var newNumString = "\(num)"
    if num > 1000 && num < 1000000 {
        newNumString = "\(newNum)k"
    } else if num > 1000000 {
        newNumString = "\(newNum)m"
    }

    return newNumString
}

formatPoints(51100) // THIS RETURNS 51K instead of 51.1K

How do I get this function to work, what am I missing?


回答1:


func formatPoints(num: Double) ->String{
    let thousandNum = num/1000
    let millionNum = num/1000000
    if num >= 1000 && num < 1000000{
        if(floor(thousandNum) == thousandNum){
            return("\(Int(thousandNum))k")
        }
        return("\(thousandNum.roundToPlaces(1))k")
    }
    if num > 1000000{
        if(floor(millionNum) == millionNum){
            return("\(Int(thousandNum))k")
        }
        return ("\(millionNum.roundToPlaces(1))M")
    }
    else{
        if(floor(num) == num){
            return ("\(Int(num))")
        }
        return ("\(num)")
    }

}

extension Double {
    /// Rounds the double to decimal places value
    func roundToPlaces(places:Int) -> Double {
        let divisor = pow(10.0, Double(places))
        return round(self * divisor) / divisor
    }
}

The updated code should now not return a .0 if the number is whole. Should now output 1k instead of 1.0k for example. I just checked essentially if double and its floor were the same.

I found the double extension in this question: Rounding a double value to x number of decimal places in swift




回答2:


The extension below does the following-

  1. Will display number 10456 as 10.5k and 10006 as 10k (will not show the .0 decimals).
  2. Will do the exact above for millions and format it i.e. 10.5M and 10M
  3. Will format thousands upto 9999 in currency format i.e. with a comma like 9,999

    extension Double {
        var kmFormatted: String {
    
            if self >= 10000, self <= 999999 {
                return String(format: "%.1fK", locale: Locale.current,self/1000).replacingOccurrences(of: ".0", with: "")
            }
    
            if self > 999999 {
                return String(format: "%.1fM", locale: Locale.current,self/1000000).replacingOccurrences(of: ".0", with: "")
            }
    
            return String(format: "%.0f", locale: Locale.current,self)
        }
    }
    

Usage:

let num: Double = 1000001.00 //this should be a Double since the extension is on Double
let millionStr = num.kmFormatted
print(millionStr)

Prints 1M

And here it is in action-




回答3:


extension Int {
    var roundedWithAbbreviations: String {
        let number = Double(self)
        let thousand = number / 1000
        let million = number / 1000000
        if million >= 1.0 {
            return "\(round(million*10)/10)M"
        }
        else if thousand >= 1.0 {
            return "\(round(thousand*10)/10)K"
        }
        else {
            return "\(self)"
        }
    }
}

print(11.roundedWithAbbreviations)          // "11"
print(11111.roundedWithAbbreviations)       // "11.1K"
print(11111111.roundedWithAbbreviations)    // "11.1 M"



回答4:


Some Change in Answer(For Int and correct for million):

func formatPoints(num: Int) ->String{
    let thousandNum = num/1000
    let millionNum = num/1000000
    if num >= 1000 && num < 1000000{
        if(thousandNum == thousandNum){
            return("\(thousandNum)k")
        }
        return("\(thousandNum)k")
    }
    if num > 1000000{
        if(millionNum == millionNum){
            return("\(millionNum)M")
        }
        return ("\(millionNum)M")
    }
    else{
        if(num == num){
            return ("\(num)")
        }
        return ("\(num)")
    }

}



回答5:


For swift 4.0. its work completely fine and answer based on @user3483203

Function for convert Double value to String

func formatPoints(num: Double) ->String{
    var thousandNum = num/1000
    var millionNum = num/1000000
    if num >= 1000 && num < 1000000{
        if(floor(thousandNum) == thousandNum){
            return("\(Int(thousandNum))k")
        }
        return("\(thousandNum.roundToPlaces(places: 1))k")
    }
    if num > 1000000{
        if(floor(millionNum) == millionNum){
            return("\(Int(thousandNum))k")
        }
        return ("\(millionNum.roundToPlaces(places: 1))M")
    }
    else{
        if(floor(num) == num){
            return ("\(Int(num))")
        }
        return ("\(num)")
    }

}

Make one Double extension

extension Double {
    /// Rounds the double to decimal places value
    mutating func roundToPlaces(places:Int) -> Double {
        let divisor = pow(10.0, Double(places))
        return Darwin.round(self * divisor) / divisor
    }
}

Usage of above function

UILABEL.text = formatPoints(num: Double(310940)!)

Output :




回答6:


To add to the answers, here's a Swift 4.X version of this using a loop to easily add/remove units if necessary:

extension Double {
    var shortStringRepresentation: String {
        if self.isNaN {
            return "NaN"
        }
        if self.isInfinite {
            return "\(self < 0.0 ? "-" : "+")Infinity"
        }
        let units = ["", "k", "M"]
        var interval = self
        var i = 0
        while i < units.count - 1 {
            if abs(interval) < 1000.0 {
                break
            }
            i += 1
            interval /= 1000.0
        }
        // + 2 to have one digit after the comma, + 1 to not have any.
        // Remove the * and the number of digits argument to display all the digits after the comma.
        return "\(String(format: "%0.*g", Int(log10(abs(interval))) + 2, interval))\(units[i])"
    }
}

Examples:

$ [1.5, 15, 1000, 1470, 1000000, 1530000, 1791200000].map { $0.shortStringRepresentation }
[String] = 7 values {
  [0] = "1.5"
  [1] = "15"
  [2] = "1k"
  [3] = "1.5k"
  [4] = "1M"
  [5] = "1.5M"
  [6] = "1791.2M"
}



回答7:


Solution above (from @qlear) in Swift 3:

func formatPoints(num: Double) -> String {
    var thousandNum = num / 1_000
    var millionNum = num / 1_000_000
    if  num >= 1_000 && num < 1_000_000 {
        if  floor(thousandNum) == thousandNum {
            return("\(Int(thousandNum))k")
        }
        return("\(thousandNum.roundToPlaces(1))k")
    }
    if  num > 1_000_000 {
        if  floor(millionNum) == millionNum {
            return "\(Int(thousandNum))k"
        }
        return "\(millionNum.roundToPlaces(1))M"
    }
    else{
        if  floor(num) == num {
            return "\(Int(num))"
        }
        return "\(num)"
    }
}

extension Double {
    // Rounds the double to decimal places value
    mutating func roundToPlaces(_ places : Int) -> Double {
        let divisor = pow(10.0, Double(places))
        return (self.rounded() * divisor) / divisor
    }
}



回答8:


Based on the solution from @qlear.
I've noticed that if the number was exactly 1000000, it would return 1000000 unformatted.
So I've added that into the function. I also included negative values.. since not everyone is always making a profit!

func formatPoints(num: Double) ->String{
    let thousandNum = num/1000
    let millionNum = num/1000000
    if num > 0
    {
        if num >= 1000 && num < 1000000{
            if(floor(thousandNum) == thousandNum){
                return("\(Int(thousandNum))k")
            }
            return("\(round1(thousandNum, toNearest: 0.01))k")
        }
        if num > 1000000{
            if(floor(millionNum) == millionNum){
                return("\(Int(thousandNum))k")
            }
            return ("\(round1(millionNum, toNearest: 0.01))M")
        }
        else if num == 1000000
        {
            return ("\(round1(millionNum, toNearest: 0.01))M")
        }
        else{
            if(floor(num) == num){
                return ("\(Int(num))")
            }
            return ("\(round1(num, toNearest: 0.01))")
        }
    }
    else
    {

        if num <= -1000 && num > -1000000{
            if(floor(thousandNum) == thousandNum){
                return("\(Int(thousandNum))k")
            }
            return("\(round1(thousandNum, toNearest: 0.01))k")
        }
        if num < -1000000{
            if(floor(millionNum) == millionNum){
                return("\(Int(thousandNum))k")
            }
            return ("\(round1(millionNum, toNearest: 0.01))M")
        }
        else if num == -1000000
        {
            return ("\(round1(millionNum, toNearest: 0.01))M")
        }
        else{
            if(floor(num) == num){
                return ("\(Int(num))")
            }
            return ("\(round1(num, toNearest: 0.01))")
        }
    }

}

And the number extension of course:

extension Double {
    /// Rounds the double to decimal places value
    func round1(_ value: Double, toNearest: Double) -> Double {
        return Darwin.round(value / toNearest) * toNearest
    }

}



回答9:


Minor improvement to @chrisz answer, Swift-4 Doble extension - This works fine in all cases.

extension Double {

  // Formatting double value to k and M
  // 1000 = 1k
  // 1100 = 1.1k
  // 15000 = 15k
  // 115000 = 115k
  // 1000000 = 1m
  func formatPoints() -> String{
        let thousandNum = self/1000
        let millionNum = self/1000000
        if self >= 1000 && self < 1000000{
            if(floor(thousandNum) == thousandNum){
                return ("\(Int(thousandNum))k").replacingOccurrences(of: ".0", with: "")
            }
            return("\(thousandNum.roundTo(places: 1))k").replacingOccurrences(of: ".0", with: "")
        }
        if self > 1000000{
            if(floor(millionNum) == millionNum){
                return("\(Int(thousandNum))k").replacingOccurrences(of: ".0", with: "")
            }
            return ("\(millionNum.roundTo(places: 1))M").replacingOccurrences(of: ".0", with: "")
        }
        else{
            if(floor(self) == self){
                return ("\(Int(self))")
            }
            return ("\(self)")
        }
    }

    /// Returns rounded value for passed places
    ///
    /// - parameter places: Pass number of digit for rounded value off after decimal
    ///
    /// - returns: Returns rounded value with passed places
    func roundTo(places:Int) -> Double {
        let divisor = pow(10.0, Double(places))
        return (self * divisor).rounded() / divisor
    }
}







回答10:


Here is my approach to it.

extension Int {
func shorted() -> String {
    if self >= 1000 && self < 10000 {
        return String(format: "%.1fK", Double(self/100)/10).replacingOccurrences(of: ".0", with: "")
    }

    if self >= 10000 && self < 1000000 {
        return "\(self/1000)k"
    }

    if self >= 1000000 && self < 10000000 {
        return String(format: "%.1fM", Double(self/100000)/10).replacingOccurrences(of: ".0", with: "")
    }

    if self >= 10000000 {
        return "\(self/1000000)M"
    }

    return String(self)
}

Below are some examples:

print(913.shorted())
print(1001.shorted())
print(1699.shorted())
print(8900.shorted())
print(10500.shorted())
print(17500.shorted())
print(863500.shorted())
print(1200000.shorted())
print(3010000.shorted())
print(11800000.shorted())

913
1K
1.6K
8.9K
10k
17k
863k
1.2M
3M
11M


来源:https://stackoverflow.com/questions/36376897/swift-2-0-format-1000s-into-a-friendly-ks

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!