Swift 2.0 Format 1000's into a friendly K's
Solution 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
Solution 2
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"
Solution 3
The extension below does the following-
- Will display number 10456 as 10.5k and 10006 as 10k (will not show the
.0
decimals). - Will do the exact above for millions and format it i.e. 10.5M and 10M
-
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-
Solution 4
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"
}
Solution 5
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)")
}
}
Related videos on Youtube
BenNov
Updated on October 16, 2022Comments
-
BenNov over 1 year
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?
-
vacawama about 8 yearsYou're doing integer division which just throws away the remainder. You might want to convert to Doubles to do your math.
-
rmaddy about 8 yearsUse
NSByteCountFormatter
instead of your own code. -
pasine about 8 yearsI don't do swift, but talking from an Obj-C prospective, I would say that you are using an
Int
value as input, sonum / 1000
is probably not returning any decimals. -
Martin R about 8 yearsHave a look at stackoverflow.com/questions/35854069/… (and the linked-to threads).
-
-
BenNov about 8 yearsTried it, but when the number is below 1000 it returns it with .0 so 916 would become 916.0
-
user3483203 about 8 yearsAll you would have to do is add one more if statement if the number is less than 1000, and run the same check I ran.
-
user3483203 about 8 yearsI just updated my answer to something that works for numbers under 1000 as well.
-
Kiran Jasvanee almost 6 years@Janky I think you are making some mistake, You can check the results in answer of mine here. I have tested it properly from my side and worked well. If you have any case where it misses you can discuss here rather than directly down voting the answer.
-
AnBisw almost 6 yearsDude @Janky something is wrong either with your data or your logic. This answer works and so does the one I posted.
-
LargeGlasses almost 6 yearsPlease fix: your minimum thousand value should be >= 1000 instead of 10000
-
AnBisw almost 6 yearsNo it should not. This extension will show thousands upto 9999 in a format of 9,999 (with a comma i.e. currency format) example 1000 will be 1,000 ; 2000 will be 2,000. Anything equal to or above 10000 or less than or equal to less than 999999 will show with a 'K' format and so on.
-
LargeGlasses almost 6 yearsAh I see what you did there. Interesting. Well, for my use case, I ended up changing it to 1000. My apologies for assuming your use case was the same as mine.
-
AnBisw almost 6 yearsNo Worries, glad you figured it out.
-
Rajesh Maurya almost 6 yearsCode has some bug in swift 4.0.
-
Bassel over 5 years@Rajesh instead of round(self * divisor) / divisor, in Swift 4 do (self * divisor).rounded() / divisor
-
zardon almost 4 yearsTest case:
let values = [100, 999, 1000, 1250, 1750, 2000, 2741, 641239, -719409, 247001,999998, 10000000, 100000000, 1e10]
Doesn't seem to handle 1250, 1750, 2000, 2741, 1e10 or larger -
SwiftStudier over 3 yearsFor double 528010 this would generate "528,0K" string for countries which have different decimal separator rather than ".". It would be better to use Locale.current.decimalSeparator before zero in replacingOccurences for each value in this extension