Группировка Сломанных серий из массива - PullRequest
0 голосов
/ 13 марта 2020

У меня есть требование сгруппировать разбитую серию.

//Example
$seriesArray = array(1, 2, 3, 5, 7, 8, 11, 12, 15);
//You see numbers are not continuous here.
//Therefore i need to group the above array to seek the below output

Ожидаемый результат

Series 1 : from 1 to 3
Series 2 : 5
Series 3 : 7 and 8
Series 4 : 11 and 12
Series 5 : 15

В приведенном выше примере, как вы видите, серия 1 группируется от 1 до 3 (так как значений больше 2), а в сериях 2 и 5, где нет преемственности, показаны единственные значения. и в сериях 3 и 4, он показывает 2 значения с двумя последовательными значениями.

Что я пробовал

function groupSeries($mainArray, $comboArr=array()) {
   $getRange = range(min($mainArray), max($mainArray)); //Expected Range
   $diffArr  = array_diff($getRange, $mainArray); //Difference of what is expected
   $ranges   = array();
   $initiateKey = 0;
   foreach($diffArr as $indKey=>$indVal) {
      if(!empty($mainArray[$initiateKey])) {
         $ranges[] = range($mainArray[$initiateKey], $getRange[$indKey-1]);
         $initiateKey = $indKey;
      }
   }
   return showRanges($ranges);
}
function showRanges($getRanges) {
   $i = 1;
   foreach($getRanges as $indRange) {
     $arrCount = count($indRange);
     echo "Series $i : ";
     switch($arrCount) {
        case 1 : echo $indRange[0]; break;
        case 2 : echo $indRange[0]." and ".$indRange[1]; break;
        default: echo "From ".min($indRange)." to ".max($indRange); break;
     }
     $i++;
     echo "\n";
   }
}

$seriesArray = array(1, 2, 3, 5, 7, 8, 11, 12, 15);
groupSeries($seriesArray);

Вышеприведенная серия массивов терпит неудачу с текущим выводом как

Series 1 : From 1 to 3
Series 2 : 5
Series 3 : 8
Series 4 : From 9 to 15

Вышеприведенная пробная версия работает с некоторыми сценариями ios, но у многих не работает.

Ответы [ 4 ]

1 голос
/ 13 марта 2020

Пожалуйста, посмотрите на этот подход. Я надеюсь, что его не думал, чтобы простой. Пожалуйста, скажите мне, если я что-то пропустил:

function groupSeries2($mainArray){
    sort($mainArray);
    $groups=[];
    $group_start=$mainArray[0];
    $group_last=$group_start;
    foreach ($mainArray as $value) {
        if($group_last+1 == $value){
            //continuous series
            $group_last=$value;
        }
        else{
            //interrupted series
            $groups[]=[$group_start,$group_last];
            $group_start=$value;
            $group_last=$group_start;
        }
    }
    $groups[]=[$group_start,$group_last];
    array_shift($groups);
    foreach ($groups as $group_key => $group){
        $groups[$group_key] = range($group[0],$group[1]);
    }
    return $groups;
}
1 голос
/ 13 марта 2020

Все проверки или трюки с индексами для доступа к нужным элементам в других ответах все еще кажутся немного запутанными для моих вкусов, я бы go с

function groupSeries($array) {
   $ranges = [];
   $idx = -1;
   $prev = false;
   foreach($array as $val) {
     if($prev === false || $val != $prev+1) {
       $idx++;
     }
     $ranges[$idx][] = $val;
     $prev = $val;
   }
   return showRanges($ranges);
}

Это действительно не не нужно намного больше, чем продвижение индекса того, куда поместить значение в массиве результатов, в зависимости от того, равна ли разница предыдущему значению 1 или нет.

1 голос
/ 13 марта 2020

Это также должно работать -

    $seriesArray = array(1, 2, 3, 5, 7, 8, 11, 12, 15);
    sort($seriesArray); // Sort array if required
    $all = range(min($seriesArray), max($seriesArray)); // get all possibles values in sorted manner
    $temp = array_diff($all, $seriesArray); // get the missing values
    $new = [];
    $i = 1;
    foreach ($temp as $missing) {
        // Group or extract all values present less than or equals to every missing value to get the series
        $new[$i] = array_filter($seriesArray, function($v) use($missing) {
            return $v <= $missing;
        });
        // remove already grouped values
        $seriesArray = array_diff($seriesArray, $new[$i]);
        $i++;
    }
    // merge the remaining values or end values & remove empty values
    $new = array_filter(array_merge($new, [$seriesArray]));

$new будет иметь все сгруппированные значения, которые вы можете представлять как хотите.

1 голос
/ 13 марта 2020

Можете ли вы попробовать следующий код

$seriesArray = array(1, 2, 3, 5, 7, 8, 11, 12, 15);
sort($seriesArray);
$result = array();

$indx = 0;
foreach($seriesArray as $key => $val){
    $tmp  = $seriesArray[$key];
    $next = (isset($seriesArray[$key+1]))? $seriesArray[$key+1] : '';
    if($next != ''){
        if(!isset($result[$indx])) $result[$indx] = array();
        if(($tmp+1) == $next ){
            $result[$indx][] = $tmp;
        }else{
            $result[$indx][] = $tmp;
            $indx++;

        }
    }else{
        $result[$indx][] = $tmp;    
    }

}
foreach($result as $key => $val){
    echo "Series ".($key+1)."  : ".implode(",",$result[$key])."<br>";
}
print_r($result);

Демо-ссылка

...