Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/292.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
合并PHP数组中的重叠范围?_Php_Arrays_Merge_Range - Fatal编程技术网

合并PHP数组中的重叠范围?

合并PHP数组中的重叠范围?,php,arrays,merge,range,Php,Arrays,Merge,Range,我有一个以下格式的数组: array( 0 => array(1, 5), 1 => array(4, 8), 2 => array(19, 24), 3 => array(6, 9), 4 => array(11, 17), ); 其中每个项目都是X到Y范围。我想要合并数组中的重叠范围,以获得更像这样的内容: array( 0 => array(1, 9), // 1-5, 4-8 and 6-9 are overlapping,

我有一个以下格式的数组:

array(
  0 => array(1, 5),
  1 => array(4, 8),
  2 => array(19, 24),
  3 => array(6, 9),
  4 => array(11, 17),
);
其中每个项目都是X到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),
);

实现这一点的最佳方法是什么?

好的,起草了这个,所以它可能有一些怪癖。用下面的数据测试了它,似乎效果很好。也许这不是最好的方法,但这是一种方法,而且确实有效。问题让我知道

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));
希望它对你有用

编辑


我知道我被打败了一个小时=\n好吧!我仍然在发帖,因为这是一种不同的方法,当然我可能会选择konforce的方法

未经测试,但这里的想法是先按第一个元素对数据进行排序,然后尽可能长地将后续元素与前一个元素合并

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)
{
返回$a[0]-$b[0];
});
$n=0$len=计数($数据);
对于($i=1;$i<$len;++$i)
{
如果($data[$i][0]>$data[$n][1]+1)
$n=$i;
其他的
{
如果($data[$n][1]<$data[$i][1])
$data[$n][1]=$data[$i][1];
未设置($data[$i]);
}
}
$data=数组_值($data);

此方法应该可以工作,但它会减慢到大范围爬网。+1这是O(n)最干净、最有效的方法。这正是我想到的算法,你比我快。对于@$data[$n][1],+1的作用是什么?使用浮点数时,这在我的情况下不起作用。@Tom,对于整数,您希望
[1,2],[3,4]
[1,4]
的一个单一范围。在这种情况下,它将读取
如果(3>2+1)
然后开始一个新范围。对于浮点数,它并没有真正的用处。+ 1,可以被删除或设置为非常小的delta(+ 00001),这取决于你认为小到可以是相同的数字。刚开始的那种已经是nlogn了。你是个邪恶的天才!!您为我节省了一些CPU和几行代码,尽管我在日期上这样做(只需在所有地方使用
strotime()
,除了第二个
if()
块(显然!),并在第一个
if()
块中添加
60
(即60秒),而不是
1
)。。我很想看看(作为更新)是否有更好的合并datetime范围的方法(尽管没有绝望到发布新问题)。
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);