У меня есть массив в следующем формате:
array( 0 => array(1, 5), 1 => array(4, 8), 2 => array(19, 24), 3 => array(6, 9), 4 => array(11, 17), );
Где каждый элемент представляет собой диапазон X-to-Y. Я хотел бы объединить перекрывающиеся диапазоны в массиве, чтобы получить что-то большее:
array( 0 => array(1, 9), // 1-5, 4-8 and 6-9 are overlapping, so they are merged 1 => array(11, 17), 2 => array(19, 24), );
Какой был бы лучший способ сделать это?
Untested, но идея здесь состоит в том, чтобы сначала отсортировать данные по первому элементу, а затем объединить последующие элементы с предыдущим как можно дольше.
usort($data, function($a, $b) { return $a[0] - $b[0]; }); $n = 0; $len = count($data); for ($i = 1; $i < $len; ++$i) { if ($data[$i][0] > $data[$n][1] + 1) $n = $i; else { if ($data[$n][1] < $data[$i][1]) $data[$n][1] = $data[$i][1]; unset($data[$i]); } } $data = array_values($data);
неusort($data, function($a, $b) { return $a[0] - $b[0]; }); $n = 0; $len = count($data); for ($i = 1; $i < $len; ++$i) { if ($data[$i][0] > $data[$n][1] + 1) $n = $i; else { if ($data[$n][1] < $data[$i][1]) $data[$n][1] = $data[$i][1]; unset($data[$i]); } } $data = array_values($data);
$input = array( 0 => array(1, 5), 1 => array(4, 8), 2 => array(19, 24), 3 => array(6, 9), 4 => array(11, 17), ); $tmpArray = array(); foreach($input as $rangeSet) { $tmpArray = array_unique(array_merge($tmpArray,range($rangeSet[0],$rangeSet[1]))); } sort($tmpArray); $oldElement = array_shift($tmpArray); $newArray = array(array($oldElement)); $ni = 0; foreach($tmpArray as $newElement) { if ($newElement > $oldElement+1) { $newArray[$ni++][] = $oldElement; $newArray[$ni][] = $newElement; } $oldElement = $newElement; } $newArray[$ni++][] = $oldElement; var_dump($newArray);
Хорошо, разработал это, так что у него могут быть причуды. Протестировал его с данными, представленными ниже, и, казалось, работал нормально. Возможно, это не лучший способ сделать это, но это один из способов, и он работает. Вопросы дайте мне знать.
function combineRange($array) { if (is_array($array)) { // Sort the array for numerical order sort($array); // Set Defaults $prev = array(); $prev_key = null; foreach ($array as $key => $item) { // First time around setup default data if (empty($prev)) { $prev = $item; $prev_key = $key; continue; } if ($item[0] >= $prev[0] && $item[0] <= $prev[1]) { // Incase the last number was less than do not update if ($array[$prev_key][1] < $item[1]) $array[$prev_key][1] = $item[1]; unset($array[$key]); }else { $prev_key = $key; } $prev = $item; } } return $array; } $array = array( 5 => array(13, 16), 0 => array(1, 5), 1 => array(4, 8), 2 => array(19, 24), 3 => array(6, 9), 4 => array(11, 17), 6 => array(21, 30), ); var_dump(combineRange($array));
сfunction combineRange($array) { if (is_array($array)) { // Sort the array for numerical order sort($array); // Set Defaults $prev = array(); $prev_key = null; foreach ($array as $key => $item) { // First time around setup default data if (empty($prev)) { $prev = $item; $prev_key = $key; continue; } if ($item[0] >= $prev[0] && $item[0] <= $prev[1]) { // Incase the last number was less than do not update if ($array[$prev_key][1] < $item[1]) $array[$prev_key][1] = $item[1]; unset($array[$key]); }else { $prev_key = $key; } $prev = $item; } } return $array; } $array = array( 5 => array(13, 16), 0 => array(1, 5), 1 => array(4, 8), 2 => array(19, 24), 3 => array(6, 9), 4 => array(11, 17), 6 => array(21, 30), ); var_dump(combineRange($array));
Выходы:
array(3) { [0]=> array(2) { [0]=> int(1) [1]=> int(9) } [3]=> array(2) { [0]=> int(11) [1]=> int(17) } [5]=> array(2) { [0]=> int(19) [1]=> int(30) } }
Надеюсь, он работает на тебя!
РЕДАКТИРОВАТЬ
Я вижу, что я был избит на час = \ О, хорошо! Я все еще размещаю, поскольку это другой метод, и я, скорее всего, выбрал бы метод konforce.