将数字数组和连字符连接的数字范围扩展为整数数组

12

我尝试将一串数字以及带有连字符的数字(作为范围表达式)归一化/扩展/水合/翻译,使之成为整数值的数组。

示例输入:

$array = ["1","2","5-10","15-20"];

应该变成:

$array = [1,2,5,6,7,8,9,10,15,16,17,18,19,20];

我正在研究的算法是:

//get the array values with a range in it :
$rangeArray = preg_grep('[-]',$array);

这里将包含["5-10", "16-20"];然后:

foreach($rangeArray as $index=>$value){
    $rangeVal = explode('-',$value);
    $convertedArray = range($rangeVal[0],$rangeVal[1]);
}

转换后的数组现在将包含["5","6","7","8","9","10"];

我现在面临的问题是,如何从原始数组中弹出值"5-10",并将这些值插入到$convertedArray中,以便我拥有以下值:

$array = ["1","2",**"5","6","7","8","9","10"**,"16-20"];

我该如何在范围字符串的位置插入一个或多个值?或者有没有更简洁的方法将由数字和范围值组成的数组转换为正确顺序的数字数组?


2
array_splice() 是你要找的函数,不过如果你不关心条目的顺序,也可以使用 array_merge() - Mark Baker
你能提供一个例子,说明我如何在我的情况下使用它吗? - muffin
我尝试了数组合并,但是我必须消除那些带有“5-10”和其他范围值的元素,然后将“规范化”的值插入该范围字符串的索引中。 - muffin
array_splicerange()结合使用,你就可以实现你想要的功能。 - Andrei
8个回答

4

给你。

我尽量将代码最小化了。

考虑下面的初始数组,

$array = ["1","2","5-10","15-20"];

如果你想用一个新的数组来代替$array,请将第一次出现的$array改为任何你想要的名称。

$array = call_user_func_array('array_merge', array_map(function($value) {
            if(1 == count($explode = explode('-', $value, 2))) {
                return [(int)$value];
            }
            return range((int)$explode[0], (int)$explode[1]);
        }, $array));

现在,$array 变成了:
$array = [1,2,5,6,7,8,9,10,15,16,17,18,19,20];

注意事项:

  • 将每个转换后的成员都转换为整数
  • 如果提供了15-20-25,则考虑15-20并忽略其余部分
  • 如果提供了15a-20b,则视为15-20,这是通过使用-进行拆分后转换为整数的结果,15a变为15
  • 将数组键转换为从0开始的数字升序排列
  • 仅当给定数组按单个成员和范围成员的升序排序时,新数组才会被排序

3

试一下这个:

<?php
$array = ["1","2","5-10","15-20"];

$newdata = array();
foreach($array as $data){
    if(strpos($data,'-')){

        $range = explode('-', $data);
        for($i=$range[0];$i<=$range[1];$i++){
            array_push($newdata, $i);
        }
    }
    else{
        array_push($newdata, (int)$data);
    }

}

        echo "<pre>";
print_r($array);
        echo "</pre>";
        echo "<pre>";
print_r($newdata);
        echo "</pre>";

Result:

Array
(
    [0] => 1
    [1] => 2
    [2] => 5-10
    [3] => 15-20
)
Array
(
    [0] => 1
    [1] => 2
    [2] => 5
    [3] => 6
    [4] => 7
    [5] => 8
    [6] => 9
    [7] => 10
    [8] => 15
    [9] => 16
    [10] => 17
    [11] => 18
    [12] => 19
    [13] => 20
)

问题解决了!

2
更简洁更短的答案。 在Ideone中查看
$new_array = array();  

foreach($array as $number){
  if(strpos($number,'-')){
     $range = explode('-', $number);  
     $new_array = array_merge($new_array, range($range[0],$range[1]));
  } 
  else{
     $new_array[] = (int) $number;
  }
}

var_dump($new_array);

它的作用是:["1","2",array(),array()]; - muffin
演示也是错误的...如果您查看原始数组的索引2,它包含另一个数组。 - muffin
@muffin 已更新,请查看。 - Muhammet

2
使用 range 和 array_merge 处理非数字值:
$array = ["1","2","5-10","15-20"];

$newArray = [];
array_walk(
    $array,
    function($value) use (&$newArray) {
        if (is_numeric($value)) {
            $newArray[] = intval($value);
        } else {
            $newArray = array_merge(
                $newArray,
                call_user_func_array('range', explode('-', $value))
            );
        }
    }
);

var_dump($newArray);

2

找到最小值和最大值,并用它们创建数组会更容易。以下是一个示例:

$in = ["1","2","5-10","15-20"];
$out = normalizeArray($in);
var_dump($out);

function normalizeArray($in)
{
    if(is_array($in) && sizeof($in) != 0)
    {
        $min = null;
        $max = null;
        foreach($in as $k => $elem)
        {
            $vals = explode('-', $elem);
            foreach($vals as $i => $val)
            {
                $val = intval($val);
                if($min == null || $val < $min)
                {
                    $min = $val;
                }
                if($max == null || $val > $max)
                {
                    $max = $val;
                }
            }
        }

        $out = array();
        for($i = $min; $i <= $max; $i++)
        {
            $out[] = $i;
        }

        return $out;
    }
    else
    {
        return array();
    }
}

2

这里是您需要的信息。

<?php
$array = ["1","2","5-10","15-20"];
$newArr = array();
foreach($array as $item){
    if(strpos($item, "-")){
        $temp = explode("-", $item);
        $first = (int) $temp[0];
        $last = (int) $temp[1];
        for($i = $first; $i<=$last; $i++){
            array_push($newArr, $i);
        }
    }
    else
        array_push($newArr, $item);
}
print_r($newArr);
?>

1

try this:

$array = ["1","2","5-10","15-20"];
$result = [];

foreach ($array as $a) {
    if (strpos($a,"-")!== false){
        $tmp = explode("-",$a);
        for ($i = $tmp[0]; $i<= $tmp[1]; $i++) $result[] = $i;
    } else {
        $result[] = $a;
    }
}

var_dump($result);

1
你没有完成一点。
$array = ["1","2","5-10","15-20"];
// need to reverse order else index will be incorrect after inserting
$rangeArray = array_reverse( preg_grep('[-]',$array), true);

$convertedArray = $array;

foreach($rangeArray as $index=>$value) {

    $rangeVal = explode('-',$value);
    array_splice($convertedArray, $index, 1, range($rangeVal[0],$rangeVal[1]));
}

print_r($convertedArray);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接