patternphpMinor
Aggregate array values into ranges
Viewed 0 times
arrayintorangesvaluesaggregate
Problem
In five minutes I made a pretty ugly looking function. Can you help before I have to commit the code into history?
Requirements:
I would like a function that takes an array of numbers, and returns an
array of ranges. Ideally remove the duplicate line.
Sample Input:
Output:
Winning Entries:
My attempt:
Requirements:
I would like a function that takes an array of numbers, and returns an
array of ranges. Ideally remove the duplicate line.
Sample Input:
Array(1,2,3,4,5,6,10,11,12,13,20,24)
Output:
Array
(
[0] => 1-6
[1] => 10-13
[2] => 20
[3] => 24
)
Winning Entries:
Pseudo code
PHP
My attempt:
$myArray = array(1,2,3,4,5,6,10,11,12,13,20,24);
$rangeArray = array();
$start = $end = current($myArray);
foreach($myArray as $range){
if($range - $end > 1){
$rangeArray[] = ($start == $end)?$start:$start."-".$end;
$start = $range;
}
$end = $range;
}
$rangeArray[] = ($start == $end)?$start:$start."-".$end;
print_r($rangeArray);
Solution
While these may not be any shorter or more efficient than existing answers, perhaps with a slightly different approach they still bring something to the table and might be considered a little less 'ugly'.
Essentially the GetRanges function I've written does the following:
-
Take a parameter-supplied array of numbers (
-
We next create a multi-dimensional array (
For options 2 and 3 where the function is expanded upon for a simple array:
For option 3 where the function is expanded upon to return a string:
Option 1: If you want your function to return a multi-dimensional array:
Output:
Option 2: If you want your function to return a simple array:
Output:
Option 3: If you want your function to return a string:
Output:
Essentially the GetRanges function I've written does the following:
-
Take a parameter-supplied array of numbers (
$aNumbers), remove any duplicates from the array and then sort them numerically lowest to highest.-
We next create a multi-dimensional array (
$aGroups) and working sequentially through the array of numbers ($aNumbers): Except for the first number which we just add to $aGroups to get us started, for each consecutive number $i > 0, if the previous number $aNumbers[$i-1] is equal to the current number minus 1 $aNumbers[$i] - 1 then the current number is added to the same group because its consecutive and belongs to that range, otherwise the current number is added to $aGroups as a new sub-array with one entry array( $aNumbers[$i] ).For options 2 and 3 where the function is expanded upon for a simple array:
- A new array (
$aRanges) is created and for each$aGroupsrecord, if the first entry of the sub-array is the only entry then a new entry is added to$aRangesfor just this number, otherwise a new entry is added to$aRangesspecifying the first number in the range followed by a hyphen followed by the last number in the range.
For option 3 where the function is expanded upon to return a string:
- The
implodefunction is used to create a comma-separated list of all the entries in the$aRangesarray and return this as a string.
Option 1: If you want your function to return a multi-dimensional array:
0 && ( $aNumbers[$i-1] == $aNumbers[$i] - 1 ))
array_push( $aGroups[count($aGroups)-1], $aNumbers[$i] );
else
array_push( $aGroups, array( $aNumbers[$i] ));
}
return $aGroups;
}
$aNumbers = array( 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 20, 24 );
print_r( GetRanges( $aNumbers ));Output:
Array (
[0] => Array ( [0] => 1, [1] => 2, [2] => 3, [3] => 4, [4] => 5, [5] => 6 )
[1] => Array ( [0] => 10, [1] => 11, [2] => 12, [3] => 13 )
[2] => Array ( [0] => 20 )
[3] => Array ( [0] => 24 )
)Option 2: If you want your function to return a simple array:
0 && ( $aNumbers[$i-1] == $aNumbers[$i] - 1 ))
array_push( $aGroups[count($aGroups)-1], $aNumbers[$i] );
else
array_push( $aGroups, array( $aNumbers[$i] ));
}
$aRanges = array();
foreach( $aGroups as $aGroup ) {
if( count( $aGroup ) == 1 )
$aRanges[] = $aGroup[0];
else
$aRanges[] = $aGroup[0] . '-' . $aGroup[count($aGroup)-1];
}
return $aRanges;
}
$aNumbers = array( 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 20, 24 );
print_r( GetRanges( $aNumbers ));Output:
Array ( [0] => 1-6, [1] => 10-13, [2] => 20, [3] => 24 )Option 3: If you want your function to return a string:
0 && ( $aNumbers[$i-1] == $aNumbers[$i] - 1 ))
array_push( $aGroups[count($aGroups)-1], $aNumbers[$i] );
else
array_push( $aGroups, array( $aNumbers[$i] ));
}
$aRanges = array();
foreach( $aGroups as $aGroup ) {
if( count( $aGroup ) == 1 )
$aRanges[] = $aGroup[0];
else
$aRanges[] = $aGroup[0] . '-' . $aGroup[count($aGroup)-1];
}
return implode( ',', $aRanges );
}
$aNumbers = array( 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 20, 24 );
echo( GetRanges( $aNumbers ));Output:
1-6,10-13,20,24Code Snippets
<?php
function GetRanges( $aNumbers ) {
$aNumbers = array_unique( $aNumbers );
sort( $aNumbers );
$aGroups = array();
for( $i = 0; $i < count( $aNumbers ); $i++ ) {
if( $i > 0 && ( $aNumbers[$i-1] == $aNumbers[$i] - 1 ))
array_push( $aGroups[count($aGroups)-1], $aNumbers[$i] );
else
array_push( $aGroups, array( $aNumbers[$i] ));
}
return $aGroups;
}
$aNumbers = array( 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 20, 24 );
print_r( GetRanges( $aNumbers ));Array (
[0] => Array ( [0] => 1, [1] => 2, [2] => 3, [3] => 4, [4] => 5, [5] => 6 )
[1] => Array ( [0] => 10, [1] => 11, [2] => 12, [3] => 13 )
[2] => Array ( [0] => 20 )
[3] => Array ( [0] => 24 )
)<?php
function GetRanges( $aNumbers ) {
$aNumbers = array_unique( $aNumbers );
sort( $aNumbers );
$aGroups = array();
for( $i = 0; $i < count( $aNumbers ); $i++ ) {
if( $i > 0 && ( $aNumbers[$i-1] == $aNumbers[$i] - 1 ))
array_push( $aGroups[count($aGroups)-1], $aNumbers[$i] );
else
array_push( $aGroups, array( $aNumbers[$i] ));
}
$aRanges = array();
foreach( $aGroups as $aGroup ) {
if( count( $aGroup ) == 1 )
$aRanges[] = $aGroup[0];
else
$aRanges[] = $aGroup[0] . '-' . $aGroup[count($aGroup)-1];
}
return $aRanges;
}
$aNumbers = array( 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 20, 24 );
print_r( GetRanges( $aNumbers ));<?php
function GetRanges( $aNumbers ) {
$aNumbers = array_unique( $aNumbers );
sort( $aNumbers );
$aGroups = array();
for( $i = 0; $i < count( $aNumbers ); $i++ ) {
if( $i > 0 && ( $aNumbers[$i-1] == $aNumbers[$i] - 1 ))
array_push( $aGroups[count($aGroups)-1], $aNumbers[$i] );
else
array_push( $aGroups, array( $aNumbers[$i] ));
}
$aRanges = array();
foreach( $aGroups as $aGroup ) {
if( count( $aGroup ) == 1 )
$aRanges[] = $aGroup[0];
else
$aRanges[] = $aGroup[0] . '-' . $aGroup[count($aGroup)-1];
}
return implode( ',', $aRanges );
}
$aNumbers = array( 1, 2, 3, 4, 5, 6, 10, 11, 12, 13, 20, 24 );
echo( GetRanges( $aNumbers ));Context
StackExchange Code Review Q#80080, answer score: 5
Revisions (0)
No revisions yet.