如有$array=$array(2001,2002,2003,2007,2008,2009,2010,2011,3015,4052,4053,4054)表示成200[1-2]|200[7-9]|201[0-1]|3015|405[2-4]
要求:1、$array中元素是任意多个,每个元素可以是任意数字但不重复
      2、输出结果要符合正则表达式
      3、要考虑周全。例如单个不连续数字的处理,数组只有一个元素的情况
新手求助求助

解决方案 »

  1.   

    $ar = array(2001,2002,2003,2007,2008,2009,2010,2011,3015,4052,4053,4054);$last = $min = $ar[0];
    for($i=1; $i<count($ar); $i++) {
      $v = $ar[$i];
      if($v == $last+1 && substr($v, -1) > substr($last, -1)) {
        $last = $v;
        $min = min($min, $last);
      }else {
        if($last == $min)
          $r[] = $last;
        else
          $r[] = sprintf("%s[%s-%s]", substr($min, 0, -1), substr($min, -1), substr($last, -1));
        $last = $min = $v;
      }
    }
    if($last != $min) {
          $r[] = sprintf("%s[%s-%s]", substr($min, 0, -1), substr($min, -1), substr($last, -1));
    }
    echo join('|', $r);
    200[1-3]|200[7-9]|201[0-1]|3015|405[2-4]
      

  2.   

    checkbox做的复选框。有N个选项,每个选项依次代表数字1到N,我可以选中其中若干个数据,这些数据不一定连续,假设将选中的数据放在$array中,在提交checkbox时 要求以正则形式返回选中的数字。不知道我说清楚没。。
      

  3.   


    //我也来一个。。
    $array=array(2001,2002,2003,2007,2008,2009,2010,2011,3015,4052,4053,4054);
    $rs = array();
    $keys = array();
    for($i=1; $i<count($array); $i++) {
        if($array[$i-1]+1 != $array[$i]) {
            $keys[] = $i;
        }
    }
    $rs = array();
    $keys[] = count($array);
    for($i=0; $i<count($keys); $i++) {
        $startKey = $i-1 < 0 ? 0 : $i-1;
        
        $startValue = $i-1 >= 0 ? $keys[$startKey] : 0;
        $tmp = array_slice($array, $startValue, $keys[$i]-$startValue);
        if(count($tmp)>1) {
            $headLen = strlen($tmp[0]) - strlen(count($tmp));
            $head = substr($tmp[0], 0, $headLen);
            $foot = '['.substr($tmp[0], $headLen) . '-' . substr(end($tmp), $headLen) . ']';
            $rs[] = $head . $foot;
        }
        else {
            $rs[] = $tmp[0];
        }
        
    }
    echo implode('|', $rs);
    /**
    输出结果:
    200[1-3]|200[7-1]|3015|405[2-4]
    */
      

  4.   

    红色警告版主2#  和我的(10楼)均出现问题。。如果 $array(9998, 9999, 10000, 10001); 跨了位数就会出现问题。经测试:
    版主:200[1-3]|200[7-9]|201[0-1]|3015|405[2-4]|999[8-9]|1000[0-1]
    我的:200[1-3]|200[7-1]|3015|405[2-4]|999[8-01]哈哈。。继续优化。。
      

  5.   

    不好意思,上面说的,版主的不知对不对,视情况吧
    而我的,肯定错了,呵呵。重新优化一下,跨位数的,也按一个区间显示。$array=array(2001,2002,2003,2007,2008,2009,2010,2011,3015,4052,4053,4054, 9998, 9999, 10000, 10001);
    $rs = array();
    $keys = array();
    for($i=1; $i<count($array); $i++) {     //将不连续的数的key记录
        if($array[$i-1]+1 != $array[$i]) {
            $keys[] = $i;
        }
    }
    $rs = array();
    $keys[] = count($array);
    for($i=0; $i<count($keys); $i++) {
        $startKey = $i-1 < 0 ? 0 : $i-1;
        $startValue = $i-1 >= 0 ? $keys[$startKey] : 0;
        $tmp = array_slice($array, $startValue, $keys[$i]-$startValue);     //从上面记录的key,截取不同长度
        if(strlen($tmp[0]) != strlen(end($tmp))) {
            $rs[] = '[' . $tmp[0] . '-' . end($tmp) . ']';      //不同位数
        }
        elseif(count($tmp)>1) {         //位数相同
            $headLen = strlen($tmp[0]) - strlen(count($tmp));//计算相同的位数
            $rs[] = substr($tmp[0], 0, $headLen) . '['.substr($tmp[0], $headLen) . '-' . substr(end($tmp), $headLen) . ']';
        }
        else {      //单独一个数
            $rs[] = $tmp[0];
        }}
    echo implode('|', $rs);
    /**
    输出结果:
    200[1-3]|200[7-1]|3015|405[2-4]|[9998-10001]
    */
      

  6.   

    混分$arr = array(2001,2002,2003,2007,2008,2009,2010,2011,3015,4052,4053,4054);$arr_k = array_map(create_function('$v', 'return substr($v,0,-1);'), $arr);
    $arr_v = array_map(create_function('$v', 'return substr($v,-1);'), $arr);$pattern = '';
    $time = 0;
    for ($i = 1; $i <= count($arr_k); $i++){
    if ($arr_k[$i] == $arr_k[$i-1]){//值与前一个相等
    if ($arr_v[$i] == $arr_v[$i-1] + 1 ){//键连续,记录连续次数
    $time++;
    }
    else{
    $pattern .= sprintf('%d[%d-%d]|',$arr_k[$i],$arr_v[$i-1-$time],$arr_v[$i-1],$time);
    $time = 0;
    }
    }
    elseif ($time != 0) {//不相等,但有累加记录
    $pattern .= sprintf('%d[%d-%d]|',$arr_k[$i-1],$arr_v[$i-1-$time],$arr_v[$i-1]);
    $time = 0;
    }
    else {
    $pattern .= sprintf('%d|',$arr_k[$i-1].$arr_v[$i-1]);
    }
    }echo $pattern;
      

  7.   

    这样写可能更清晰些
    $ar = array(2001,2002,2003,2007,2008,2009,2010,2011,3015,4052,4053,4054);
    $i = 0;
    foreach($ar as $v) {
      $k = substr($v, 0, -1);
      $v = substr($v, -1);
      if(! isset($r[$k])) $i = 0;
      if(isset($r[$k][$i]) && $v != max($r[$k][$i])+1) $i++;
      $r[$k][$i][] = $v;
    }foreach($r as $k=>$t)
      foreach($t as $v)
        if(count($v) == 1) $o[] = $k . $v[0];
        else $o[] = sprintf('%s[%s-%s]', $k, min($v), max($v));echo join('|', $o);
      

  8.   

    抱歉,又有疑问了。。如果我需要另外一种结果比如:
            8032-9110=>803[2-9]|80[4-9][0-9]|8[1-9][0-9][0-9]|90[0-9][0-9]|910[0-9]|9110 8102-8321=>810[2-9]|81[1-9][0-9]|82[0-9][0-9]|83[0-1][0-9]|832[0-1] 8000-8100=>80[0-9][0-9]|8100 8000-8099=>80[0-9][0-9] 8000-9999=>[8-9][0-9][0-9][0-9] 8000-8088=>80[0-7][0-9]|808[0-8]

            6079-6088=>6079|608[0-8]
    怎么做?
      

  9.   


    <?php
    $arr = array(2001,2002,2003,2004,2005,2007,2008,2009,2010,2011,3015,4052,4053,4054);
    function foobar($arr , $start =0, $flag=true){
    if($start > count($arr)-1)return;
    if((($arr[$start+1] - $arr[$start])== 1)&&((substr($arr[$start+1] , -1 ) - substr($arr[$start] , -1 ))  == 1 )){
    $str = ($flag ? ($start > 0 ? "|" :"") . substr($arr[$start] , 0,(strlen($arr[$start])-1))."[" : "")."|".substr($arr[$start] ,(strlen($arr[$start])-1),1);
    $flag = false;
    }else{
    $new_flag = (($arr[$start] - $arr[$start-1])== 1)&&((substr($arr[$start] , -1 ) - substr($arr[$start-1] , -1 ))  == 1 );
    $me = substr($arr[$start] ,(strlen($arr[$start])-1),1);
    $str = $flag ? "|".$arr[$start]:( $new_flag ? $str = "|".$me."]" : $str = "]|".$me);
    $flag = true;
    }
    $eco .=$str.foobar($arr , $start+1 , $flag);
    return $eco ;
    }echo foobar($arr);
    ?>
      

  10.   

    再发一遍吧<?php
    $arr = array(2001,2002,2003,2004,2005,2007,2008,2009,2010,2011,3015,4052,4053,4054);
    function foobar($arr , $start =0, $flag=true){
    if($start > count($arr)-1)return;
    if((($arr[$start+1] - $arr[$start])== 1)&&((substr($arr[$start+1] , -1 ) - substr($arr[$start] , -1 ))  == 1 )){
    $str = ($flag ? ($start > 0 ? "|" :"") . substr($arr[$start] , 0,(strlen($arr[$start])-1))."[" : "").($flag ? substr($arr[$start] ,(strlen($arr[$start])-1),1) :"");
    $flag = false;
    }else{
    $new_flag = (($arr[$start] - $arr[$start-1])== 1)&&((substr($arr[$start] , -1 ) - substr($arr[$start-1] , -1 ))  == 1 );
    $me = substr($arr[$start] ,(strlen($arr[$start])-1),1);
    $str = $flag ? "|".$arr[$start]:( $new_flag ? $str = "-".$me."]" : $str = "]|".$me);
    $flag = true;
    }
    $eco .=$str.foobar($arr , $start+1 , $flag);
    return $eco ;
    }
    echo foobar($arr);
    ?>
      

  11.   

    呃~~我个人觉得
    [8032-9110]

    803[2-9]|80[4-9][0-9]|8[1-9][0-9][0-9]|90[0-9][0-9]|910[0-9]|9110
    简洁得多,
    而且前者的匹配效率也明显高于后者。
    下面是我针对前者写的代码,不合楼主的要求,请便。
    <?php$aCheckboxValue = array(1,2,3,4,200,400,2001,5600,2002,2003,2035,5601);//将数组从小到大排序
    sort($aCheckboxValue);//获取数组长度
    $length = count($aCheckboxValue);
    $i = 0;
    $pattern = '';//通过循环处理数组
    while ($i < $length) {
        $i ++;

    //循环判断之后的数组元素是否连续
    for ($j = $i; $j < $length; $j ++) {
    if ($aCheckboxValue[$j] - $aCheckboxValue[$j - 1] != 1) {
    //若不连续则跳出循环
    break;
    } else {
    //若连续则继续判断下一个元素
        continue;
    }
    }
    if ($j - $i > 0) {
        //有连续的则以字符组形式作为一个可选项追加到$pattern后面
    $pattern .= '['.$aCheckboxValue[$i - 1].'-'.$aCheckboxValue[$j - 1].']|';
    } else {
    //没有连续的则直接作为一个可选项追加到$pattern后面
    $pattern .= $aCheckboxValue[$i - 1].'|';
    }

    //移动数组下标位置到当前
    $i = $j;
    }//取出$pattern收尾的|符号
    $pattern = trim($pattern, '| ');echo $pattern;
    ?>
      

  12.   

    自己写了个,貌似解决了。只是感觉太笨了
    $min=8032;$max=9110;
    $cha=strlen($max)-strlen($min);
    for($i=0;$i<$cha;$i++){
       $min="0".$min;
       }
    //找出$min于$max的相同部分$same,以及不同部分
    $same="";
    for($i=1;$i<strlen($min);$i++)
       if (substr($min,0,-$i)==substr($max,0,-$i)){
       $same=substr($min,0,-$i);$min=substr($min,-$i);$max=substr($max,-$i);break;
       }
    //找出左边及中间部分
    $middle=null;
    if(substr($max,0,1)-substr($min,0,1)>=2){
                                         $middle=sprintf('[%s-%s]',substr($min,0,1)+1,substr($max,0,1)-1);
     }
    for($i=1;$i<strlen($min);$i++){
       $o=null;
          if(substr($min,-$i,1)<9) {
          if($i==1){
                    $o=sprintf('%s[%s-%s]',substr($min,0,-$i),substr($min,-$i,1),9);
                    //echo $o."<br>";
                    }else{
                       $o=sprintf('%s[%s-%s]',substr($min,0,-$i),substr($min,-$i,1)+1,9);
                    }
    //echo $o."<br>";

       }else{
          if($i==1){
               $o=sprintf('%s',$min);
       }else{
       }
    }

    if($o!=null){
                for($j=1;$j<$i;$j++){
                $o=$o."["."0"."-"."9"."]";
            }
    $o=preg_replace('/^0+/si','',$o);//去掉前边的0
                $d[]=$o;
       }

    if($middle!=null)$middle=$middle."["."0"."-"."9"."]";
     }
     
      if($middle!=null)$d[]=$middle;
       //echo $middle."<br>";
     //找出右边部分.合并最后结果保存至$result
     for($i=1;$i<strlen($max);$i++){
       $k=null;
        if(substr($max,$i,1)>0){
       if($i==strlen($max)-1){
         $k=sprintf('%s[%s-%s]',substr($max,0,$i),0,substr($max,$i,1));
       }else{
       $k=sprintf('%s[%s-%s]',substr($max,0,$i),0,substr($max,$i,1)-1);
       }
    }else{
       if($i==strlen($max)-1){
       $k=sprintf('%s',$max);
       }else{
       }
     }
     
          if($k!=null){
         for($j=1;$j<strlen($max)-$i;$j++){
         //echo $k."<br />";
             $k=$k."["."0"."-"."9"."]";
         }
     
        $d[]=$k;
    }
    //$k="";
    $result=join("|",$d);
        }
    echo $result."<br>";
     
      

  13.   

    <?phpfunction change_rule($min,$max){//使$min $max长度相同
    /*sort($array);
    $min=current($array);$max=end($array);if(strlen($max)==1&&$max!=$min){
        $result="[$min-$max]";
        return $result;
    }elseif($max=$min&&strlen($max)==1){
        $result=$min;
        return $result;
    }*/
    $cha=strlen($max)-strlen($min);
    for($i=0;$i<$cha;$i++){
       $min="0".$min;
       }
    //找出$min于$max的相同部分$same,以及不同部分
    $same=null;
    for($i=1;$i<strlen($min);$i++)
       if (substr($min,0,-$i)==substr($max,0,-$i)){
       $same1=substr($min,0,-$i);$min=substr($min,-$i);$max=substr($max,-$i);$same=$same1;break;
       }
       //$min="$min";$max="$max";
     //分类处理  
    if(strlen($max)==1){
            $result="[$min-$max]";
           }else{
       //$same=$same1;
    //找出左边及中间部分
    $middle=null;
    if(substr($max,0,1)-substr($min,0,1)>=2){
                                         $middle=sprintf('[%s-%s]',substr($min,0,1)+1,substr($max,0,1)-1);
     }
    for($i=1;$i<strlen($min);$i++){
       $o=null;
          if(substr($min,-$i,1)<9) {
          if($i==1){
                    $o=sprintf('%s[%s-%s]',substr($min,0,-$i),substr($min,-$i,1),9);
                    }else{
                       $o=sprintf('%s[%s-%s]',substr($min,0,-$i),substr($min,-$i,1)+1,9);
                    }

       }else{
          if($i==1){
               $o=sprintf('%s',$min);
       }else{
       }
    }

    if($o!=null){
                for($j=1;$j<$i;$j++){
                $o=$o."["."0"."-"."9"."]";
            }
    if(!$same) $o=preg_replace('/^0+/','',$o);//去掉开始的0
                $d[]=$o;
       }
    $left=join("|",$d);
    if($middle!=null)$middle=$middle."["."0"."-"."9"."]";
     }
     
      if($middle!=null)$d[]=$middle;
      
     //找出右边部分.合并最后结果保存至$result
     for($i=1;$i<strlen($max);$i++){
       $k=null;
        if(substr($max,$i,1)>0){
       if($i==strlen($max)-1){
         $k=sprintf('%s[%s-%s]',substr($max,0,$i),0,substr($max,$i,1));
       }else{
       $k=sprintf('%s[%s-%s]',substr($max,0,$i),0,substr($max,$i,1)-1);
       }
    }else{
       if($i==strlen($max)-1){
       $k=sprintf('%s',$max);
       }else{
       }
     }
     //加上[0-9]
          if($k!=null){
         for($j=1;$j<strlen($max)-$i;$j++){
             $k=$k."["."0"."-"."9"."]";
         }
     
        $d[]=$k;
    }

    $result=join("|",$d);
          }
        }
        
        
        
        
        //去掉形如[0-0]的部分,用单个数字代替
        for($i=0;$i<=9;$i++){
             $result=str_replace("[$i-$i]","$i",$result);
            }
        $_array=explode("|",$result);//用“|”分解
        //与相同部分组合
        foreach ($_array as $key=>$value){
            $value="$same".$value;
            $_array[$key]=$value;
            }
            
        $result=join("|",$_array);//用‘|’分解
        return $result;
        
     }
     
    function createarray($min=null,$max=null){
        for($min;$min<$max+1;$min++){
            $newarray[]=$min;
        }
        return $newarray;
    }
    //改为正则表达式
    function num_change ($arr=array()){
        sort($arr);
        $min=current($arr);$max=end($arr);    if(strlen($max)==1){
            $result="[$min-$max]";
           }else{
           $result=change_rule($min,$max);
        }     for($i=0;$i<=9;$i++){
             $result=str_replace("[$i-$i]","$i",$result);
            }
        return $result;
    }//分解数组为二维数组
    function array_change($originalarray=array()){
        sort($originalarray);
        $son_array=array();
        foreach ($originalarray as $value){
            if(!$son_array||$son_array[count($son_array)-1]==$value-1){
             $son_array[]=$value;   
            }else{
                $final_array[]=$son_array;
                $son_array=array($value);
            }
        }
        if($son_array) $final_array[]=$son_array;
        return $final_array;
    }function array_result($array=array()){
        if(!$array) return;
        
        $arr=array_change($array);
        $a=array();
        foreach($arr as $value){
            $a[]=num_change($value);
            //print_r($a);
        }
        $result=join('|',$a);
        return $result;
    }$arr=createarray(8032,9110);
    echo array_result($arr);
    ?>