4

UPDATE

For JavaScript, see CMS's implementation below. It is much more elegant than the one I provide in the body of this Q.


// formats a number similar to the way stack exchange sites // format reputation. e.g. // for numbers< 10000 the output is '9,999' // for numbers > 10000 the output is '10k' with one decimal place when needed function getRepString(rep) { var repString;

    if (rep < 1000)
    {
        repString = rep;
    }
    else if (rep < 10000)
    {
        var mod = rep % 1000;

        repString = ((rep - mod) / 1000)
        + ","
        + ('000' + mod.toString()).slice(-3);
    }
    else
    {
        repString = (rep / 1000).toFixed(1).replace(".0", "") + "k";
    }

    return repString.toString();
}

Output:

  • getRepString(999) == '999'
  • getRepString(1000) == '1,000'
  • getRepString(9999) == '9,999'
  • getRepString(10000) == '10k'
  • getRepString(10100) == '10.1k'

Post an implementation in the language of your choice.

6
  • a more elegant implementation is heading our way... i hope. Jul 5, 2010 at 9:24
  • You mean one that we don't have to manually do? Surely thats the whole point of giving us the "raw" score? We can format it how we like.
    – JonB
    Jul 5, 2010 at 10:20
  • @jonb - no, i mean that someone showed me a more elegant way to do this and i encouraged him to post it here and hope he does, otherwise I am going to have to post it myself. and, yes, raw data is appropriate for an api return, but i as well as others, in various languages, wish to present this information in a more friendly format. that is what this post is about. Jul 5, 2010 at 15:50
  • It looks like most of the implementations here are slightly off. Numbers like 10999 would show as 11k. Also 12452 would be 12.5k. SO rounds up.
    – jjnguy
    Aug 14, 2010 at 22:14
  • @jjn - so what you are saying is that the examples shown truncate instead of round up as SO does? I can't speak for any but stackapps.com/questions/1012/… which performs as desired. Aug 14, 2010 at 22:37
  • @Code, Yeah. I didn't test out any of them, but it looks liek a bunch of them truncate instead of rounding.
    – jjnguy
    Aug 14, 2010 at 23:03

8 Answers 8

5

Here you go, another JavaScript approach, originally posted on SO:

function getRepString (rep) {

  rep = rep+''; // coerce to string

  if (rep < 1000) { // return the same number
    return rep; 
  }

  if (rep < 10000) { // place a comma between

    return rep.charAt(0) + ',' + rep.substring(1);
  } 

  // divide and format
  return (rep/1000).toFixed(rep % 1000 != 0)+'k';

}

Check the output results here.

2
  • 3
    + for you. this is the way to do it in JS. I have removed the JS tag, so there is no 'right' answer now, just an x-language implementation free for all. Thanks for schooling me. Jul 5, 2010 at 17:00
  • Using this one now, had a convoluted algorithm for the rep < 10000 case. Jul 7, 2010 at 2:39
5

Objective-C:

This should work on iOS 3.2, iOS 4.0 and Mac OS X 10.4 - 10.6 :

I don't have multiple returns because I like a single exit point in my code. Hence I use my trusty friend returnable.

- (NSString*) stringForReputationFormatted:(NSNumber*)reputation
{
    NSString *returnable = nil;
    long rep = [reputation longValue];
    NSString *returnable = nil;

    if (rep < 1000) {
        returnable = [reputation stringValue];
    }
    else if (rep < 10000) {
        NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
        [numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
        returnable = [numberFormatter stringForObjectValue:reputation];
        [numberFormatter release];
    }
    else {
        NSString *repStr    = [reputation stringValue];
        NSString *whole     = [repStr substringToIndex:[repStr length]-3];
        NSString *decimal   = [repStr substringWithRange:NSMakeRange([repStr length]-3, 1)];
        if ([decimal intValue] != 0) {
            returnable = [whole stringByAppendingFormat:@".%@K", decimal];
        } else {
            returnable = [whole stringByAppendingFormat:@"K"];
        }
    }
    return returnable;
}

Edit: Apologies for the code being so long. NSDateFormatter isn't working right on iOS atm, so I needed to format the string manually.

Tests to confirm:

Raw:-1 Converted:-1
Raw:0 Converted:0
Raw:1 Converted:1
Raw:2 Converted:2
Raw:10 Converted:10
Raw:100 Converted:100
Raw:101 Converted:101
Raw:999 Converted:999
Raw:1000 Converted:1,000
Raw:1001 Converted:1,001
Raw:3500 Converted:3,500
Raw:6790 Converted:6,790
Raw:8900 Converted:8,900
Raw:9999 Converted:9,999
Raw:10000 Converted:10K
Raw:10099 Converted:10K
Raw:10500 Converted:10.5K
Raw:11600 Converted:11.6K
Raw:10799 Converted:10.7K
Raw:99899 Converted:99.8K
Raw:195999 Converted:195.9K
10
  • @code poet: gracious! Aug 14, 2010 at 22:08
  • Well, this isn't 100% the same as SO. Raw:10799 Converted:10.7K should actually be 10.8K. SO rounds up.
    – jjnguy
    Aug 14, 2010 at 22:13
  • @jinguy: Looks like i'm not the only one rounding down though. Do you have a link as to where it says it rounds up? Aug 14, 2010 at 22:15
  • 1
    @Brock, no. I believe everyone does it wrong. Everyone is simply truncating. It really doesn't matter that much though...
    – jjnguy
    Aug 14, 2010 at 22:18
  • See this example: stackoverflow.com/users/21632/adam-bellaire
    – jjnguy
    Aug 14, 2010 at 22:19
  • @jinguy: Okay, well I thought you shouldn't be displaying for example: 10K UNTIL you have actually reached it. Seems like a false reading to round up. Aug 14, 2010 at 22:21
  • @Brock, I believe 9999 does show as 9,999. It's just when you get into th2 5 digits that the rounding kicks in.
    – jjnguy
    Aug 14, 2010 at 22:22
  • @jinguy: Fair enough, I'm going to round down for my SO app though :) Aug 14, 2010 at 22:25
  • @brock, yeah. I would do it the easy way too. That's how we do it in StackWrap4J.
    – jjnguy
    Aug 14, 2010 at 22:27
  • stackapps.com/questions/1012/… rounds up as expected. Aug 14, 2010 at 23:02
4

Here's a Java implementation using NumberFormat.

public static void main(String[] args) {

    int[] values = { 999, 1000, 9999, 10000, 10100 };

    for( int rep : values ) {
        System.out.println( formatRep(rep) );
    }
}

public static String formatRep(int rep) {
    if(rep < 1000) {
        return rep + "";
    }
    if(rep < 10000) {
        NumberFormat formatter = new DecimalFormat("#,###");
        return formatter.format(rep);
    }
    else {
        NumberFormat formatter = new DecimalFormat("#,###.#k");
        double d = rep / 1000.0;
        return formatter.format(d);
    }
}

Output:

999
1,000
9,999
10k
10.1k

I'm not sure about that last format for numbers greater than 999k. I guess we have a few years to wait and see. :)

0
4

c#

Rounds up - same same SO.

public string FormatReputation(int value)
{
    var rep = System.Convert.ToDouble(value);
        
    if (rep < 10000)
    {
        return rep.ToString("N0");
    }
    
    return (rep / 1000)
         .ToString(rep % 1000 == 0 ? "" : "F1") + 'k';
}
  • 100 => "100"
  • 1200 => "1,200"
  • 9999 => "9,999"
  • 10000 => "10k"
  • 10200 => "10.2k"

confirmation as per jjng's comment

  • 10999 => "11k"
  • 12452 => "12.5k"
3

Here's a quick and dirty way of how I did mine in .NET

Visual Basic

    Public Shared Function GetReputation(ByVal input As Integer) As String

        Dim _input As String = input.ToString
        Select Case input
            Case Is > 99999 : Return _input.Remove(_input.Length - 3) & "k"
            Case Is > 9999 : Return Math.Round(Double.Parse(input / 1000), 1).ToString & "k"
            Case Is > 999 : Return String.Format("{0:N0}", input)
            Case Else : Return _input
        End Select
    End Function
0
3

Just for completeness, here is the C# version I am using ported from the VB version given by @rockinthesixstring:

private string FormatReputation(int reputation)
{
     string s = reputation.ToString();
     if (reputation > 99999)
         return s.Remove(s.Length - 3) + "k";
     else if (reputation > 9999)
         return Math.Round((double)reputation / (double)1000, 1).ToString() + "k";
     else if (reputation > 999)
         return String.Format("{0:N0}", reputation);
     return s;
}
0
3

These are great feature ideas - thanks for the tips!

I've more or less converted CMS' answer to Python:

class FormattedReputation(int):
    def format(rep):
        """Formats the reputation score like it is formatted on the sites. Heavily based on CMS' JavaScript implementation at
        http://stackapps.com/questions/1012/how-to-format-reputation-numbers-similar-to-stack-exchange-sites/1019#1019"""
        str_rep = str(rep)

        if rep < 1000:
            return str_rep
        elif rep < 10000:
            return '%s,%s' % (str_rep[0], str_rep[1:])
        elif rep % 1000 == 0:
            return '%dk' % (rep / 1000.0)
        else:
            return '%.1fk' % (rep / 1000.0)

This is used automatically as an alternative to int for reputation fields in Py-StackExchange, so using it on its own is slightly awkward:

lucas@ubuntu:~/projects/py-stackexchange$ python -i se_inter.py
>>> FormattedReputation(100).format()
'100'
>>> FormattedReputation(1000).format()
'1,000'
>>> FormattedReputation(1240).format()
'1,240'
>>> FormattedReputation(12403).format()
'12.4k'
>>> FormattedReputation(100000).format()
'100k'
2
  • Thanks for that. you might include some test runs, both for your edification and others. Aug 14, 2010 at 22:07
  • Do you mean like that? Aug 14, 2010 at 23:26
2

Good ole' PHP:

// Any number larger than 1000 gets returned like '4.5k'

function Numberify($num)
{
    if($num > 1000)
        return (floor($num / 100) / 10) . 'k';
    return $num
}

Do you like the name of the function? :)

4
  • @code: I really need a sensible name for the function... any ideas? Jul 10, 2010 at 20:25
  • 1
    makeanumberstackoverflowystyle
    – nobody
    Jul 10, 2010 at 20:33
  • i am using formatNumber for lack of a better term. no need to be more explicit as the dev will be calling it as a member of your SO client library so context can be assumed. Jul 10, 2010 at 21:55
  • you're missing a few conversions. Numbers between 1000 and 9999 are formatted to look like 1,000, numbers between 10000 and 99999 are formatted to look like 10.4k, and finally what your method does is for numbers greater than 100000. Jul 15, 2010 at 14:54

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .