How to convert sequence of numbers in an array to

2020-01-30 06:16发布

In javascript how to convert sequence of numbers in an array to range of numbers?

eg. [2,3,4,5,10,18,19,20] to [2-5,10,18-20]

21条回答
走好不送
2楼-- · 2020-01-30 06:58

An adaptation of CMS's javascript solution for Cold Fusion

It does sort the list first so that 1,3,2,4,5,8,9,10 (or similar) properly converts to 1-5,8-10.

<cfscript>
    function getRanges(nArr) {
        arguments.nArr = listToArray(listSort(arguments.nArr,"numeric"));
        var ranges = [];
        var rstart = "";
        var rend = "";
        for (local.i = 1; i <= ArrayLen(arguments.nArr); i++) {
            rstart = arguments.nArr[i];
            rend = rstart;
            while (i < ArrayLen(arguments.nArr) and (val(arguments.nArr[i + 1]) - val(arguments.nArr[i])) == 1) {
                rend = val(arguments.nArr[i + 1]); // increment the index if the numbers sequential
                i++;
            }
            ArrayAppend(ranges,rstart == rend ? rstart : rstart & '-' & rend);
        }
        return arraytolist(ranges);
    }
</cfscript>
查看更多
干净又极端
3楼-- · 2020-01-30 06:59

I found this answer useful, but needed a Python version:

def GroupRanges(items):
  """Yields 2-tuples of (start, end) ranges from a sequence of numbers.

  Args:
    items: an iterable of numbers, sorted ascendingly and without duplicates.

  Yields:
    2-tuples of (start, end) ranges.  start and end will be the same
    for ranges of 1 number
  """
  myiter = iter(items)
  start = myiter.next()
  end = start
  for num in myiter:
    if num == end + 1:
      end = num
    else:
      yield (start, end)
      start = num
      end = num
  yield (start, end)


numbers = [1, 2, 3, 5, 6, 7, 8, 9, 10, 20]
assert [(1, 3), (5, 10), (20, 20)] == list(GroupRanges(numbers))
assert [(1, 1)] == list(GroupRanges([1]))
assert [(1, 10)] == list(GroupRanges([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]))
查看更多
放我归山
4楼-- · 2020-01-30 06:59

You could iterate over the numbers and see if the next number is 1 bigger then the current number. So have a:

struct range {
    int start;
    int end;
} range;

where if array[i+1] == array[i]+1; (where i is the currently observed number) then range.end = array[i+1];. Then you progress to the next i; If array[i+1] != array[i]+1; then range.end = array[i];

you could store the ranges in a vector< range > ranges;

printing would be easy:

for(int i = 0; i < ranges.size(); i++) {
    range rng = (range)ranges.at(i);
    printf("[%i-%i]", rng.start, rng.end);
}
查看更多
霸刀☆藐视天下
5楼-- · 2020-01-30 07:02

Here is an algorithm that I made some time ago, originally written for C#, now I ported it to JavaScript:

function getRanges(array) {
  var ranges = [], rstart, rend;
  for (var i = 0; i < array.length; i++) {
    rstart = array[i];
    rend = rstart;
    while (array[i + 1] - array[i] == 1) {
      rend = array[i + 1]; // increment the index if the numbers sequential
      i++;
    }
    ranges.push(rstart == rend ? rstart+'' : rstart + '-' + rend);
  }
  return ranges;
}

getRanges([2,3,4,5,10,18,19,20]);
// returns ["2-5", "10", "18-20"]
getRanges([1,2,3,5,7,9,10,11,12,14 ]);
// returns ["1-3", "5", "7", "9-12", "14"]
getRanges([1,2,3,4,5,6,7,8,9,10])
// returns ["1-10"]
查看更多
爱情/是我丢掉的垃圾
6楼-- · 2020-01-30 07:02

Here is a port of CMS's code for BASH:

#!/usr/bin/env bash
# vim: set ts=3 sts=48 sw=3 cc=76 et fdm=marker: # **** IGNORE ******
get_range() { RANGE= # <-- OUTPUT                  **** THIS   ******
   local rstart rend i arr=( "$@" )  # ported from **** JUNK   ******
   for (( i=0 ; i < $# ; i++ )); do  # http://stackoverflow.com
      (( rstart = arr[i] ))          # /a/2270987/912236
      rend=$rstart; while (( arr[i+1] - arr[i] == 1 )); do
      (( rend = arr[++i] )); done; (( rstart == rend )) &&
   RANGE+=" $rstart" || RANGE+=" $rstart-$rend"; done; } # }}}
查看更多
我命由我不由天
7楼-- · 2020-01-30 07:03

Here is a version for Perl:

use strict;
use warnings;

my @numbers = (0,1,3,3,3,4,4,7,8,9,12, 14, 15, 19, 35, 35, 37, 38, 38, 39);
@numbers =  sort {$a <=> $b} @numbers ; # Make sure array is sorted.

# Add "infinity" to the end of the array.
$numbers[1+$#numbers] = undef ;

my @ranges = () ; # An array where the range strings are stored.

my $start_number = undef ;
my $last_number  = undef ;
foreach my $current_number (@numbers)
{
  if (!defined($start_number))
  {
    $start_number = $current_number ;
    $last_number  = $current_number ;
  }
  else
  {
    if (defined($current_number) && (($last_number + 1) >= $current_number))
    {
      $last_number = $current_number ;
      next ;
    }
    else
    {
      if ($start_number == $last_number)
      {
        push(@ranges, $start_number) ;
      } 
      else
      {
        push(@ranges, "$start_number-$last_number") ;
      }
      $start_number = $current_number ;
      $last_number  = $current_number ;
    }
  }
}

# Print the results
print join(", ", @ranges) . "\n" ; 
# Returns "0-1, 3-4, 7-9, 12, 14-15, 19, 35, 37-39"
查看更多
登录 后发表回答