Вроде простой алгоритм, который раньше бы написал за 20 минут, сейчас башка тупит от большого кол-ва проектов, предновогодней загрузки... Задача: Вывести сокращенную последовательность чисел. То есть везде где это можно заменить, к примеру "1,2,3,4" на "1-4". Массив $aFloors: ключи - пример исходных данных, значение - то, что должно получиться... Алгоритм: PHP: <?php $aFloors = array( '9,7,6,5,4,2,1' => '1,2,4-7,9', '9,8,7,5,4,3,2,1' => '1-5,7-9', '7,6,5,8,4,3,2' => '2-8', '5,6,9,4,3,2' => '2-6,9', '1,9,7,5' => '1,5,7,9', '9,8,6,4,2,1' => '1,2,4,6,8,9', '9,8,6,4,7,2,1' => '1,2,4,6-9', '8' => '8', '2,7,8,9' => '2,7-9', '2,6,8,9' => '2,6,8,9' ); ?> <style type="text/css"> .v TD { font: 12px Arial; padding: 2px 10px; } </style> <table class="v"> <?php foreach ($aFloors as $key => $val) { $res = GetFloors($key); echo <<<EOF <tr> <td>{$key}</td><td>{$val}</td><td>{$res}</td> </tr> EOF; } function GetFloors($s) { // разбираем по запятой $m = explode(',', (string)$s); if ( sizeof($m) == 1 ) return $m[0]; // сортируем sort($m); $count = sizeof($m); $s = ''; $i = 0; while($i<$count) { $z = $m[$i]; // начальное значение $p_end = $i; // конечное значение // поиск максимальной последовательности for($j=$i+1;$j<=$count;$j++) { $z++; // увеличиваем начальное значение if ( $j == $count || $m[$j] != $z ) { // если это последний элемент или проверяемое не равно начальному значению $p_end = $j-1; // записываем конечный индекс найденной последовательности break; // выходим из поиска } } // $i - индекс начального значения последовательности, $p_end - индекс конечного значения последовательности if ( $p_end-$i>1 ) { // если разница м/у индексами последовательности > 1 $s .= $m[$i] . '-' . $m[$p_end]; } elseif ( $p_end - $i == 1 ) { // если разница = 1 $s .= $m[$i] . ',' . $m[$p_end]; } else { // если это последний элемент $s .= $m[$p_end]; } // если это не последний элемент, ставим запятую if ( $p_end+1 != $count ) $s .= ','; // начальное значение = следующее за конечным (+1) $i = $p_end + 1; } return $s; } ?> </table> Кто видит как можно сделать проще?
PHP: <?php $aFloors = array( '9,7,6,5,4,2,1' => '1,2,4-7,9', '9,8,7,5,4,3,2,1' => '1-5,7-9', '7,6,5,8,4,3,2' => '2-8', '5,6,9,4,3,2' => '2-6,9', '1,9,7,5' => '1,5,7,9', '9,8,6,4,2,1' => '1,2,4,6,8,9', '9,8,6,4,7,2,1' => '1,2,4,6-9', '8' => '8', '2,7,8,9' => '2,7-9', '2,6,8,9' => '2,6,8,9' ); $result = array(); foreach ($aFloors as $k => $null) { $values = explode(',', $k); sort($values); $pv = max($values); $j = 0; foreach ($values as $v) { if ($v - $pv > 1) { $j++; } $result[$k][$j][] = $v; $pv = $v; } } print_r($result); Первое что пришло в голову.
Хорошая штука хоть мозг размять Заодно учет пустых строк и повторяющихся чисел PHP: <?php header('Content-type: text/plain; charset=utf-8'); $aFloors = array( '9,7,6,5,4,2,1' => '1,2,4-7,9', '9,8,7,5,4,3,2,1' => '1-5,7-9', '7,6,5,8,4,3,2' => '2-8', '5,6,9,4,3,2' => '2-6,9', '1,9,7,5' => '1,5,7,9', '9,8,6,4,2,1' => '1,2,4,6,8,9', '9,8,6,4,7,2,1' => '1,2,4,6-9', '8' => '8', '2,7,8,9' => '2,7-9', '2,6,8,9' => '2,6,8,9' ); $array = array_keys($aFloors); foreach ($array as $a) echo $a.' => '.get($a)."\n"; function get($str) { $values = explode(',', $str); if (!isset($values[0])) return ''; sort($values); $str = $values[0]; for ($i = 1, $s = 0; isset($values[$i]); $i++) { if ($values[$i] - $values[$i-1] > 1) { if ($s !== false) $str .= get_interval($values[$s], $values[$i-1]); $s = false; $str .= ','.$values[$i]; } else { if ($s === false) $s = $i-1; } } if ($s !== false) $str .= get_interval($values[$s], $values[$i-1]); return $str; } function get_interval($a, $b) { if ($b - $a > 1) return '-'.$b; elseif ($b == $a) return ''; else return ','.$b; } ?>
Вопрос автору - числа перечислены в строку или это массив из числел, который надо вывести в виде строки, в которой по мере возможности указаны интервалы?