В JavaScript, как преобразовать последовательность чисел в массиве к диапазону чисел?
например. [2,3,4,5,10,18,19,20]
к [2-5,10,18-20]
; For all cells of the array
;if current cell = prev cell + 1 -> range continues
;if current cell != prev cell + 1 -> range ended
int[] x = [2,3,4,5,10,18,19,20]
string output = '['+x[0]
bool range = false; --current range
for (int i = 1; i > x[].length; i++) {
if (x[i+1] = [x]+1) {
range = true;
} else { //not sequential
if range = true
output = output || '-'
else
output = output || ','
output.append(x[i]','||x[i+1])
range = false;
}
}
Что-то вроде этого.
Вот алгоритм, который я сделал некоторое время назад , первоначально написанный для C #, теперь я перенес его на 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"]
Вы можете перебирать числа и смотреть, будет ли следующее число на 1 больше текущего. Итак, есть:
struct range {
int start;
int end;
} range;
где if array [i + 1] == array [i] +1;
(где i - текущее наблюдаемое число)
then диапазон. конец = массив [i + 1];
. Затем вы переходите к следующему i
; Если array [i + 1]! = Array [i] +1;
, то range.end = array [i];
, вы можете сохранить диапазоны в векторе < диапазон> диапазоны;
распечатать было бы просто:
for(int i = 0; i < ranges.size(); i++) {
range rng = (range)ranges.at(i);
printf("[%i-%i]", rng.start, rng.end);
}
Просто получаю удовольствие от решения от CMS:
function getRanges (array) {
for (var ranges = [], rend, i = 0; i < array.length;) {
ranges.push ((rend = array[i]) + ((function (rstart) {
while (++rend === array[++i]);
return --rend === rstart;
})(rend) ? '' : '-' + rend));
}
return ranges;
}
Вот мой взгляд на это ...
function getRanges(input) {
//setup the return value
var ret = [], ary, first, last;
//copy and sort
var ary = input.concat([]);
ary.sort(function(a,b){
return Number(a) - Number(b);
});
//iterate through the array
for (var i=0; i<ary.length; i++) {
//set the first and last value, to the current iteration
first = last = ary[i];
//while within the range, increment
while (ary[i+1] == last+1) {
last++;
i++;
}
//push the current set into the return value
ret.push(first == last ? first : first + "-" + last);
}
//return the response array.
return ret;
}
Вот версия для 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"
Если вам просто нужна строка, представляющая диапазон, то вы найдете среднюю точку вашей последовательности, и это станет вашим средним значением (10 в вашем примере). Затем возьмите первый элемент в последовательности и элемент, который непосредственно предшествует средней точке, и постройте представление первой последовательности. Проделайте ту же процедуру, чтобы получить последний элемент и элемент, который следует сразу за средней точкой, и постройте представление последней последовательности.
// Provide initial sequence
var sequence = [1,2,3,4,5,6,7,8,9,10];
// Find midpoint
var midpoint = Math.ceil(sequence.length/2);
// Build first sequence from midpoint
var firstSequence = sequence[0] + "-" + sequence[midpoint-2];
// Build second sequence from midpoint
var lastSequence = sequence[midpoint] + "-" + sequence[sequence.length-1];
// Place all new in array
var newArray = [firstSequence,midpoint,lastSequence];
alert(newArray.join(",")); // 1-4,5,6-10
Демонстрация онлайн: http://jsbin.com/uvahi/edit
Я как раз искал именно эту вещь. Мне нужна была версия PHP, поэтому я перенес решение CMS. Вот он, для тех, кто останавливается на этом вопросе и ищет то же самое:
function getRanges( $nums )
{
$ranges = array();
for ( $i = 0, $len = count($nums); $i < $len; $i++ )
{
$rStart = $nums[$i];
$rEnd = $rStart;
while ( isset($nums[$i+1]) && $nums[$i+1]-$nums[$i] == 1 )
$rEnd = $nums[++$i];
$ranges[] = $rStart == $rEnd ? $rStart : $rStart.'-'.$rEnd;
}
return $ranges;
}