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

后端 未结 13 2097
陌清茗
陌清茗 2021-01-01 12:51

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 =          


        
相关标签:
13条回答
  • 2021-01-01 13:25

    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-

    0 讨论(0)
  • 2021-01-01 13:28
    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

    0 讨论(0)
  • 2021-01-01 13:28

    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
        }
    
    }
    
    0 讨论(0)
  • 2021-01-01 13:31

    Since we all more or less disagree

    func FormatFriendly(num: Double) ->String {
        var thousandNum = num/1000
        var millionNum = num/1000000
    
        if num >= 1000 && num < 1000000{
            if(floor(thousandNum) == thousandNum){
                return("\(Int(thousandNum))K").replacingOccurrences(of: ".0", with: "")
            }
            return("\(thousandNum.roundToPlaces(places: 1))K").replacingOccurrences(of: ".0", with: "")
        }
    
        if num >= 1000000{
            //if(floor(millionNum) == millionNum){
                //return("\(Int(thousandNum))K").replacingOccurrences(of: ".0", with: "")
            //}
        return ("\(millionNum.roundToPlaces(places: 1))M").replacingOccurrences(of: ".0", with: "")
        }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 Darwin.round(self * divisor) / divisor
        }
    }
    
    0 讨论(0)
  • 2021-01-01 13:31

    I have converted @AnBisw's answer to use switch (build time friendly):

       extension Double {
        var kmFormatted: String {
            switch self {
            case ..<1_000:
                return String(format: "%.0f", locale: Locale.current, self)
            case 1_000 ..< 999_999:
                return String(format: "%.1fK", locale: Locale.current, self / 1_000).replacingOccurrences(of: ".0", with: "")
            default:
                return String(format: "%.1fM", locale: Locale.current, self / 1_000_000).replacingOccurrences(of: ".0", with: "")
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-01 13:33

    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"
    }
    
    0 讨论(0)
提交回复
热议问题