在几位兄弟的帮助下,已经出炉了一个按照自己意愿将数据入库的的PHP程序,也第一次将代码集成为函数,但貌似count_ac_pl计算函数运行效率太低了,求大师的优化建议.说明:如果数据小,程序已能运行.
<?php
  $beg_time = microtime(true);
  $beg_time *= 1000 * 1000;
  
   // $base_r=array('1,2,3,4,5,6', '1,2,3,4,5,7','1,2,3,4,5,8','1,2,3,4,5,9');
   $base_a=range(1,33);
   $base_r=combination($base_a,6);
   $rs1=combine_char($base_r) ;
   //$fp=fopen("data1.txt","w");
   // foreach ($rs1 as $value)
   // {
     //  fwrite($fp,$value,"\r\n");
   //}
    
   arraytosql($rs1) ;
   $end_time = microtime(true);
   $end_time *= 1000 * 1000;
   echo "Total time used : " . ($end_time - $beg_time) . "ms" . PHP_EOL;
   echo"total mins:". (($end_time - $beg_time)/1000/1000/60)."mins". PHP_EOL;
function count_ac_pl($base)//array $copy,array $range
    
    {  
    /***********************************    计算方法如下:    ***************************   
    * 求一组数据的 如:array(4,9,10,21,22,24)
    * 
    * 1\算术复杂度AC值:  数组中每一个数据与其他数据做差,取正值;然后统计所有不同的正值的个数D,最后得出AC=D-COUNT(ARRAY())+1;
    * 
    * 2\算术偏离度PL1值: 数组中每个数据与其他所有数据做差,取得到正值组合,取每个组合中的最小值;  然后取所有最小值中的最大值;
    * 
    * 3\整体算术偏离度PL2:整体数组range(1,33),数组中每个数据与整体数组 依次做差,取所有最小值中的最大值,应该去0;
    * 
    * **************************************************************
    * **************************************************************
    * **************************************************************
    * 
    * 第一次测试将代码集成为函数.好激动.............
    * 
    ****************************************************************/
   // $base=array(4,9,10,21,22,24);
    //count_ac_pl($base); 
        global $AC;  //开始以为后面用个return就能返回这样的值,后来一看必须要声明为全局变量才可以.
        global $PL1;
        global $PL2;
       $copy=$base;
        $range=range(1,33);
        $a=array();
        $b=array();
        $c=array();
        $d=array();
        $e=array();
        $f=array();
        $g=array();
        $j=0 ;
        $k=0;
        foreach($base as $key=>$value) {
            $ch='';
                foreach($base as $k=>$v)  {
                    $a[$j].=$ch.abs($value-$v);  //所有差值字符串形式存入一维数组$a;
                    $d[0].=','.abs($value-$v);   //全部差值字符串形式存入一维数组$d,用于AC计算
                    $ch=',' ;
                    }
            $b[$j]=explode(',',$a[$j]) ;         //取$a中的的元素将其以数组形式存储到$B中,便于统计最小值
            sort($b[$j]);
            array_shift($b[$j])    ;            //排序,去0
            $c[$j]=min($b[$j]) ;                //找出数组的最小值,存储到C数组中,为了以后能统计出C数组中的最大值即偏离度.
            $j++;
        }
        
        //下面重新循环一次计算,计算相对range数组的整体偏离度
         foreach($base as $key=>$value) {
            $ch='';
                foreach($range as $k=>$v)  {
                    $e[$k].=$ch.abs($value-$v);  //所有差值字符串形式存入一维数组$a;
                    $ch=',' ;
                    }
            $f[$k]=explode(',',$e[$k]) ;         //取$a中的的元素将其以数组形式存储到$B中,便于统计最小值
            sort($f[$k]);
            array_shift($f[$k])    ;            //排序,去0
            $g[$k]=min($f[$k]) ;                //找出数组的最小值,存储到C数组中,为了以后能统计出C数组中的最大值即偏离度.
            $k++;
        }
        
        //下面计算PL2值 ,相对整体数据的偏离度;
        $PL2=max($g) ;                          //C数组中所有最小值中的最大值
        //下面计算AC值
        $sub=explode(',',substr($d[0],1));
        $AC=count(array_count_values($sub))-count($base) ; //array_count_values() 返回一个数组,该数组用 input 数组中的值作为键名,该值在 input 数组中出现的次数作为值
        //下面计算PL1值 ,相对自身数据的偏离度;
        $PL1=max($c) ;                          //C数组中所有最小值中的最大值
        return $AC;
       // return $PL1;
        //return $PL2;
        
    }   
    
 
 function combine_char($needl){
     global $AC;  //开始以为后面用个return就能返回这样的值,后来一看必须要声明为全局变量才可以.
     global $PL1;
     global $PL2;
     $copya=$needl;
     $dqs=range(17,33);
     $jqs=array(1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33);
     $zqs=array(1,2,3,5,7,11,13,17,19,23,29,31);
     $firstarea=range(1,11)     ;
     $secondarea=range(12,22);
     $thirdarea=range(23,33);
     $zero=array(3,6,9,12,15,18,21,24,27,30,33);
     $first=array(1,4,7,10,13,16,19,22,25,28,31);
     $second=array(2,5,8,11,14,17,20,23,26,29,32);
     //$j=0;
     foreach ($copya as $key=>$value){
         global $array_mid;
         $array_mid=explode(',',$value) ;
         count_ac_pl($array_mid);
         $copya[$key].=','.array_sum($array_mid);
         $copya[$key].=','.count(array_intersect($array_mid,$dqs));
         $copya[$key].=','.count(array_intersect($array_mid,$jqs));
         $copya[$key].=','.count(array_intersect($array_mid,$zqs));
         $copya[$key].=','.count(array_intersect($array_mid,$firstarea));      //A区数
         $copya[$key].=','.count(array_intersect($array_mid,$secondarea));     //b区数
         $copya[$key].=','.count(array_intersect($array_mid,$thirdarea));    //c区数
         //print_r(array_mid);
         
         $copya[$key].=','.'$AC='.$AC;
         $copya[$key].=','.($AC+$PL1).','.($AC+$PL2);
         $copya[$key].=','.((min($array_mid)%3==1)?1:(min(explode(',',$value))%3==2?2:0));
         $copya[$key].=','.((max($array_mid)%3==1)?1:(max(explode(',',$value))%3==2?2:0));
         //$j++;
        
         
     }
     return $copya; 
              
 }
 
 function combination($numArr,$combineLen) {
  $numCt    = count($numArr);
  if($combineLen > $numCt) return;
  $bin    = str_pad('',$combineLen,'1');
  $bin    = str_pad($bin,$numCt,'0',STR_PAD_RIGHT);    
  $find    = $bin;
  $rs[]    = implode(',',array_slice($numArr,0,$combineLen));
  $jj        = 1;
  while(strrev($find) != $bin) {
    $vc=array();
    $k = explode('10',$find,2);
    $find = $find{0} === '0' ? strrev($k[0]).'01'.$k[1] : $k[0].'01'.$k[1];
    for($i=0;$i<$numCt;$i++) 
    $vc[0].=  $find[$i] ?  $numArr[$i] . "," : '';
    $rs[$jj]=substr($vc[0],0,-1);
    $jj++;
  }
  return $rs;
}function arraytosql($array_data){
    $db=new mysqli('localhost','admin','admin','ssq') ;
    $db->query("truncate table hmk");
    $idx=0;
    while($idx < count($array_data) ) {
    $ar1 = '' ;
    $ch='';
    if ($idx + 5000 < count($array_data)) 
    { $ar1 = '('.implode('),(',array_slice($array_data, $idx, 5000)).')';
     //echo '小于数组长度时的去数组剩余所有数据的$ar值跟踪='.$ar; 
    }
    else
     {
    $ar1 = '('.implode('),(',array_slice($array_data, $idx)).')';
    //echo '大于数组长度时的去数组剩余所有数据的$ar值跟踪='.$ar;   
      }  ;
      $sql = 'INSERT INTO hmk(l1,l2,l3,l4,l5,l6,NUM_L1_L6,dqs,jqs,zqs,firstarea,secondarea,thirdarea,AC,PL1,PL2,SUM_AC_PL1,SUM_AC_PL2,FIRSTBALL_012,ENDBALL_012) VALUES '; //,NUM_L1_L6,dqs,jqs,zqs,firstarea,secondarea,thirdarea,AC,PL1,PL2,SUM_AC_PL1,SUM_AC_PL2,FIRSTBALL_012,ENDBALL_012
      $sql .= $ar1;
      //$ch=',';
      //echo ' 循环次数'  ;
      //echo 'result=sql='.$sql.'<br>';  
      $result=$db->query($sql);
      //$result1=$db->query('insert into hmk(l1,l2,l3,l4,l5,l6) values(1,2,3,7,89,98)') ;
      if($result)
      echo $db->affectd_rows.'rows inserted into database.'.'goodluck' ;
      else 'sorry';
      $idx = $idx+5000;

$db->close();
}
 ?>

解决方案 »

  1.   

    不是吓到了吧!!!!程序可以运行,只不过是需要较长时间 ,生成100多万条数据,然后加工后存储到MYsql数据库,我估计是我的计算函数出了点问题,需要时间多了代码多了点,为了便于大家分析。主要目的是想知道function count_ac_pl($base)和function combine_char($needl)这两个函数的算法设计有没有好的办法,我的程序能运行,存储到数据库需要32分48秒,有时候是34分钟。function count_ac_pl($base)//array $copy,array $range
        
        {  
        /***********************************    计算方法如下:    ***************************   
        * 求一组数据的 如:array(4,9,10,21,22,24)
        * 
        * 1\算术复杂度AC值:  数组中每一个数据与其他数据做差,取正值;然后统计所有不同的正值的个数D,最后得出AC=D-COUNT(ARRAY())+1;
        * 
        * 2\算术偏离度PL1值: 数组中每个数据与其他所有数据做差,取得到正值组合,取每个组合中的最小值;  然后取所有最小值中的最大值;
        * 
        * 3\整体算术偏离度PL2:整体数组range(1,33),数组中每个数据与整体数组 依次做差,取所有最小值中的最大值,应该去0;
        * 
        * **************************************************************
        * **************************************************************
        * **************************************************************
        * 
        * 第一次测试将代码集成为函数.好激动.............
        * 
        ****************************************************************/
       // $base=array(4,9,10,21,22,24);
        //count_ac_pl($base); 
            global $AC;  //开始以为后面用个return就能返回这样的值,后来一看必须要声明为全局变量才可以.
            global $PL1;
            global $PL2;
           $copy=$base;
            $range=range(1,33);
            $a=array();
            $b=array();
            $c=array();
            $d=array();
            $e=array();
            $f=array();
            $g=array();
            $j=0 ;
            $k=0;
            foreach($base as $key=>$value) {
                $ch='';
                    foreach($base as $k=>$v)  {
                        $a[$j].=$ch.abs($value-$v);  //所有差值字符串形式存入一维数组$a;
                        $d[0].=','.abs($value-$v);   //全部差值字符串形式存入一维数组$d,用于AC计算
                        $ch=',' ;
                        }
                $b[$j]=explode(',',$a[$j]) ;         //取$a中的的元素将其以数组形式存储到$B中,便于统计最小值
                sort($b[$j]);
                array_shift($b[$j])    ;            //排序,去0
                $c[$j]=min($b[$j]) ;                //找出数组的最小值,存储到C数组中,为了以后能统计出C数组中的最大值即偏离度.
                $j++;
            }
            
            //下面重新循环一次计算,计算相对range数组的整体偏离度
             foreach($base as $key=>$value) {
                $ch='';
                    foreach($range as $k=>$v)  {
                        $e[$k].=$ch.abs($value-$v);  //所有差值字符串形式存入一维数组$a;
                        $ch=',' ;
                        }
                $f[$k]=explode(',',$e[$k]) ;         //取$a中的的元素将其以数组形式存储到$B中,便于统计最小值
                sort($f[$k]);
                array_shift($f[$k])    ;            //排序,去0
                $g[$k]=min($f[$k]) ;                //找出数组的最小值,存储到C数组中,为了以后能统计出C数组中的最大值即偏离度.
                $k++;
            }
            
            //下面计算PL2值 ,相对整体数据的偏离度;
            $PL2=max($g) ;                          //C数组中所有最小值中的最大值
            //下面计算AC值
            $sub=explode(',',substr($d[0],1));
            $AC=count(array_count_values($sub))-count($base) ; //array_count_values() 返回一个数组,该数组用 input 数组中的值作为键名,该值在 input 数组中出现的次数作为值
            //下面计算PL1值 ,相对自身数据的偏离度;
            $PL1=max($c) ;                          //C数组中所有最小值中的最大值
            return $AC;
           // return $PL1;
            //return $PL2;
            
        }   
        
     
     function combine_char($needl){
         global $AC;  //开始以为后面用个return就能返回这样的值,后来一看必须要声明为全局变量才可以.
         global $PL1;
         global $PL2;
         $copya=$needl;
         $dqs=range(17,33);
         $jqs=array(1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33);
         $zqs=array(1,2,3,5,7,11,13,17,19,23,29,31);
         $firstarea=range(1,11)     ;
         $secondarea=range(12,22);
         $thirdarea=range(23,33);
         $zero=array(3,6,9,12,15,18,21,24,27,30,33);
         $first=array(1,4,7,10,13,16,19,22,25,28,31);
         $second=array(2,5,8,11,14,17,20,23,26,29,32);
         //$j=0;
         foreach ($copya as $key=>$value){
             global $array_mid;
             $array_mid=explode(',',$value) ;
             count_ac_pl($array_mid);
             $copya[$key].=','.array_sum($array_mid);
             $copya[$key].=','.count(array_intersect($array_mid,$dqs));
             $copya[$key].=','.count(array_intersect($array_mid,$jqs));
             $copya[$key].=','.count(array_intersect($array_mid,$zqs));
             $copya[$key].=','.count(array_intersect($array_mid,$firstarea));      //A区数
             $copya[$key].=','.count(array_intersect($array_mid,$secondarea));     //b区数
             $copya[$key].=','.count(array_intersect($array_mid,$thirdarea));    //c区数
             //print_r(array_mid);
             
             $copya[$key].=','.'$AC='.$AC;
             $copya[$key].=','.($AC+$PL1).','.($AC+$PL2);
             $copya[$key].=','.((min($array_mid)%3==1)?1:(min(explode(',',$value))%3==2?2:0));
             $copya[$key].=','.((max($array_mid)%3==1)?1:(max(explode(',',$value))%3==2?2:0));
             //$j++;
            
             
         }
         return $copya; 
                  
     }定义一个小点的数据$base=array('1,2,3,4,5,6,','1,2,3,4,5,7','1,2,3,4,5,8','1,2,3,4,5,9','1,2,3,4,5,10','1,2,3,4,5,11','1,2,3,4,5,12','1,2,3,4,5,13');帮测试优化下。谢谢啦
      

  2.   

    没看算法,估计看了也不懂……只看了插入数据库的语句,你是写一句就插入一句,还是批量插入,如
    $sql="insert into a value ('1'),('2'),('3')……"
    mysql_query($sql);
      

  3.   

    一个一个来吧,首先数据库的插入批量的,50000条一次入库。时间浪费在数据计算上了。首先生成一个(1到33)的6个数的组合数据,xuzuning老兄已经帮忙给出了10移动算法,好时1分2秒。接下来我的计算过程,如将1,2,3,4,5,6这组数据的AC值  偏度值计算出来。方法就是
    1\算术复杂度AC值:  数组中每一个数据与其他数据做差,取正值;然后统计所有不同的正值的个数D,最后得出AC=D-COUNT(ARRAY())+1;
        * 
        * 2\算术偏离度PL1值: 数组中每个数据与其他所有数据做差,取得到正值组合,取每个组合中的最小值;  然后取所有最小值中的最大值;
        * 
        * 3\整体算术偏离度PL2:整体数组range(1,33),数组中每个数据与整体数组 依次做差,取所有最小值中的最大值,应该去0;
        *
    即1-2=1;1-3=2;1-4=3;1-5=4;1-6=5;然后2-3=1;2-4=2.....依次下来值到5-6=1;在所有的结果中招出来不同的值的个数d;然后用D-数组的长度6+1就是AC值。
    偏度则是:1与其他数相减然后得到一组数据,取最小值,依次下去,然后取所有最下值中的最大值就是偏度。想帮我看看这个函数写的是不是有问题吧,可以不!!~~~~谢谢啦。看别人的代码真是有难度。
      

  4.   

    算了,不求甚解了,好时38分15秒数据全部入库.以后也用不到这样的函数了!~~~结贴,xuzuning  QQ多给点,帮了不少忙..其他分数均分了...