esamattis / underscore.string

String manipulation helpers for javascript
http://esamattis.github.com/underscore.string/
3.37k stars 375 forks source link

Add ranged number formatting #244

Open jokecr opened 10 years ago

jokecr commented 10 years ago

Add a string function to collapse an array of numbers into a string. Perhaps like this?

_.range(array, [ rangeSeparator='-', breakSeparator=','])

_.range([1,2,3,5,6,7,9])
=> "1-3,5-7,9"
jordangray commented 10 years ago

TL;DR: do we default to calculating ranges based on the nearest integer, or on the smallest power of ten used by an item in the array? Should there be an argument to specify that? If so, what about values other than powers of ten? How do you deal with numbers that don't "fit"? (Skim over the tables below to get a sense of this.)


This is an interesting idea. If you really want to generalise it, there's the question of how to deal with what might be termed the granularity of the method. Would you assume:

  1. unit granularity (i.e. nearest whole number), ignoring non-integers;
  2. unit granularity, treating non-integers as a break in the range;
  3. unit granularity, treating non-integers as implying the range from the floor to the ceil;
  4. unit granularity, rounding non-integers into the nearest integer; or
  5. lowest power of ten (LPOT) used in the range?

Here are some motivational examples to illustrate the difference:

  1. [0.1, 0.2, 0.3, 0.5]

    Granularity Output
    unit, ignore non-integers ""
    unit, non-integers as breaks "0.1, 0.2, 0.3, 0.5"
    unit, non-integers as implied range "0-1"
    unit, rounded "0-1"
    lowest power of ten "0.1-0.3, 0.5"
  2. [10, 20, 30, 50]

    Granularity Output
    unit, all cases "10, 20, 30, 50"
    lowest power of ten "10-30, 50"
  3. [1, 2, 3, 3.5, 5]

    Granularity Output
    unit, ignore non-integers "1-3, 5"
    unit, non-integers as breaks "1-3, 3.5, 5"
    unit, non-integers as implied range "1-5"
    unit, rounded "1-5"
    lowest power of ten "1, 2, 3, 3.5, 5"
  4. [0.1, 0.2]

    Granularity Output
    unit, ignore non-integers ""
    unit, non-integers as breaks "0.1, 0.2"
    unit, non-integers as implied range "0-1"
    unit, rounded "0"
    lowest power of ten "0.1-0.2"

Additionally, you could allow granularity to be specified as an argument. In this case you could even permit arbitrary granularity (e.g. _.range([0, 2, 4], { granularity = 2 }) // "0-4"), but we'd still need to choose either units or LPOT as a default, and decide on a strategy for dealing with numbers that fall between granular multiples.