如何将数组数组折叠为一系列范围

时间:2015-05-22 03:13:37

标签: php arrays

我有以下数组:

$values=array(2000,2001,2002,3000,3001,3002);

我想返回一组数字范围:

$ranges=array(2000-2002,3000-3002);

我该怎么做?

2 个答案:

答案 0 :(得分:0)

我认为使用数组... map / reduce / walk函数可以有更好的解决方案,但你可以从这个开始。

$values = [2000, 2001, 2002, 3000, 3001, 3002];

sort($values);
$result = [];
$start = $prevValue = null;
foreach ($values as value) {
    if ($value - $prevValue > 1) {
        if ($start) {
            $result[] = $start == $prevValue ? $start : $start . '-' . $prevValue;
        }
        $start = $value;
    }
    $prevValue = $value;
}
$result[] = $start == $prevValue ? $start : $start . '-' . $prevValue;

答案 1 :(得分:0)

测试数据输出:

[2000,2001,2002,3000,3001,3002] => [2000-2002,3000-3002]
[2000,2001,2002,3000,3001,3002,4000] => [2000-2002,3000-3002,4000]
[] => []
[2000] => [2000]
[4001,2000] => [2000,4001]
[4001,2000,2000] => [2000,4001]

你走了:

<?php

function groupArrayHelper(array $values, array $groupArray, callable $isWithinRange) {

    if ( !$values ) {
        return $groupArray;
    }

    $lastValueInGroup = (string)$values[0];

    $group = [ $lastValueInGroup ];

    $length = sizeof( $values );

    for ( $i = 1; $i < $length; $i++ ) {
        $currentValue = $values[$i];

        if ( !$isWithinRange( $currentValue, $lastValueInGroup ) ) {
            break;
        }

        $lastValueInGroup = $currentValue;
    }

    if ( ( $lastValueInGroup - $values[0] ) > 0 ) {
        $group[] = (string)$lastValueInGroup;
    }

    $groupArray[] = implode( $group, '-' );

    $moreValues = array_slice( $values, $i );

    return groupArrayHelper( $moreValues, $groupArray, $isWithinRange );
}

function groupArray(array $values) {

    $values = array_unique( $values );
    sort( $values );

    return groupArrayHelper(
            $values,
            [ ],
            function ($x, $y) {
                return ( 1 == $x - $y );
            }
    );
}

function formatArray(array $values) {
    return sprintf( '[%s]', implode( ',', $values ) );
}

$testValues[] = array( 2000, 2001, 2002, 3000, 3001, 3002 );
$testValues[] = array( 2000, 2001, 2002, 3000, 3001, 3002, 4000 );
$testValues[] = array();
$testValues[] = array( 2000 );
$testValues[] = array( 4001, 2000 );
$testValues[] = array( 4001, 2000, 2000 );

array_map( function ($values) {

    $output = groupArray( $values );

    echo formatArray( $values ) . ' => ' . formatArray( $output ) . PHP_EOL;

}, $testValues );