去除重复数据,对多维数组排序 之 php

这几天一直在做一个需求,要求找出数据库相连的电话号码,相连的号码要求可以是前4位或前3位,可由参数控制的。如下所示:

要求找出4位4连号,输入特征号码为:1256 ;

则应该找出以下号码:+++++++ 代表手机号码中的任意前7位

+++++++1253,+++++++1254,+++++++1255,+++++++1256,+++++++1257,+++++++1258,+++++++1259

数据库为oracle,想了很久都没想到在SQL语句下功夫的方法,据说同事想到了,但经测试没有成功,待想到了数据库方法再贴.

下面写出我在PHP代码中处理的方法:

假设现在已经生成了一个二维数组,接下来我们要对这个数组中的数据进行处理,以得到要求的数据。

先将代码贴下来吧,回家理下思路

 

/*
 * add by 20071030 yangxs 添加对家庭连号的查询
 * @notes 本函数可用于对一二维数组中的数据筛选,如:一组号码尾部的几位与一个特征字符串比较,
 并得到在这组号码中与特征字符串前后(+/-1的号码,可进位,可控制是否有重号)相同的号码。
 例:$arrSrc = array(0    => array('number') => '13028101004'),
                      1    => array('number') => '13928101000'),
                     2    => array('number') => '13228101001'),
                     3    => array('number') => '13028101003'),
                     4    => array('number') => '13228101002'),
                     5    => array('number') => '13028100997'),
                     6    => array('number') => '13328100998'),
                     7    => array('number') => '13028100999'),
                     8    => array('number') => '13128101002'),
                     9    => array('number') => '13628101002'),
                     10    => array('number') => '15228100586'),
                     11    => array('number') => '13028101996'),
                     12    => array('number') => '15688899999'),
                     13    => array('number') => '15105021006'),
                     14    => array('number') => '15105021007'),
                     15    => array('number') => '15105021009'),
                     );
    $t_character    = '998';
    $repeat         = true;
    $intLinkNum     = 8; 
    则我们要得到的数据应该是:
    $arrSrc = array(0    => array('number') => '13028101996 '),
                      1    => array('number') => '13028100997 '),
                     2    => array('number') => '13328100998 '),
                     3    => array('number') => '13028100999 '),
                     4    => array('number') => '13928101000'),
                     5    => array('number') => '13228101001'),
                     6    => array('number') => '13228101002'),
                     7    => array('number') => '13128101002'),
                     8    => array('number') => '13628101002'),
                     9    => array('number') => '13028101003'),
                     10    => array('number') => '13028101004')
                     );
    也就是在998前后的数据,且相邻的数据之差应该等于1,如果中间的号码没有找到,则不再向那个方向继续查找
    如下程序     
                          
 * @param object $conn 数据库连接对象
 * @param int    $intLinkNum 要找到的号码数量 
 * @param string $t_character 特征字符串
 * @param array  $arrSrc 源数组
 * @param boolea $repeat = true 是否可以包含重复的号码
 * @return array 成功则返回一个满足家庭连号条件的数组,失败则返回一个带有错误提示的数组
*
*/
function  get_homelink_number( $arrSrc , $t_character , $intLinkNum   =   0 , $repeat   =   true )
{
    
$arrResult          =   array ();         // 最终满足条件的数组,如果没有则为出错信息如:array(0,'参数传递错误!');
     $arrMySrc          =   array ();         // 将源数组处理后的数组,其中包含一个用于排序的元素sortval
     $arrChar          =   array ();         // 特征字串数组,如传入为1258,则该数组内容为array(1256,1257,1258,1259) 等
     $strHaveChar      =   '' ;             // 将已经满足基本条件的号码特征字符记录
     $ifFound          =   false ;         // 是否能找到尾部与特征字符串相同的数据
     $intCharLen          =   strlen ( $t_character ); // 首先根据特征字符串的长度来得到要比较的尾数长度
    
    //检测传入参数

     if ( empty ( $t_character ||   count ( $arrSrc ) <= 0 )
    {
        
$arrResult          =   array ( - 1 , ' 参数传递错误! ' );
        
return   $arrResult ;
    }    
    
    
// 构造满足特征的字串数组,如:由998构造的数组为:array(998,999,997,1000,996,1001,995,1002,994,1003,993,1004,992,1005,991,1006,990)
     $arrChar [ 0 ]         =   $t_character ;
    
for ( $i   = 1 ; $i <= $intLinkNum ; $i ++ )
    {
        
// 向前加1 pow(10,$intCharLen)可以得到特征字符串进位的整数,如999+1 = 1000(10的3次方); 9999+1 = 10000(10的4次方)
         if (( $t_character   +   $i ) - pow ( 10 , $intCharLen ) >= 0 )
        {
// 进位
             $arrChar []     =   substr ( ' 0000 ' . ( $t_character + $i ) ,- ( $intCharLen + 1 ));  // 进位时向前多取一位
        } else
        {
            
$arrChar []     =   substr ( ' 0000 ' . ( $t_character + $i ) ,- $intCharLen );
        }        
        
// 向后减1
         if (( $t_character   -   $i ) >= 0 )
        {
// 只包含大于0的情况,如果小于0则暂时不处理
             $arrChar []     =   substr ( ' 0000 ' . ( $t_character - $i ) ,- $intCharLen );
        }    
    }
        
    
// 重新构造满足基本条件的数组,即在    $arrSrc.[$i].number 的最尾的几位在特征字串数组里时,将$arrSrc.[$i]保存的新的数组里,并将当前元素的特征字符串保存,供后面排序使用
     foreach ( $arrSrc   as   $arr )
    {    
        
if ( count ( $arr >   0 )
        {
            
if (( substr ( $arr [ ' number ' ] ,- ( $intCharLen   +   1 ))  -   pow ( 10 , $intCharLen ))  <=   $intLinkNum   &&  ( substr ( $arr [ ' number ' ] ,- ( $intCharLen   +   1 ))  -   pow ( 10 , $intCharLen ))  >=   0 )
            {
// 取得当前号码的尾部字符串,如果当前号码的尾部 $intCharLen + 1 位 - 特征字符串进位的整数 >=0 且 <= $intLinkNum 时,表示该号码是特征字符串的进位号码
                 $tailStr          =   substr ( $arr [ ' number ' ] ,- ( $intCharLen   +   1 ));
            }
elseif (( substr ( $arr [ ' number ' ] ,- ( $intCharLen   +   1 ))  -   pow ( 10 , $intCharLen )) < 0 )
            {
// 取得当前号码的尾部字符串,如果当前号码的尾部 $intCharLen + 1 位 - 特征字符串进位的整数 < 0 时,表示该号码是特征字符串的没有进位的号码
                 $tailStr          =   substr ( $arr [ ' number ' ] ,- ( $intCharLen ));
            }
            
            
// 查看当前号码的尾部字符串是否在特征的字串数组,如果在则写入新的数组中
             if (( count ( $arrChar >   0   &&   in_array ( $tailStr , $arrChar )))
            {
                
// 查看当前号码的尾部字符串是否等于传入的特征字符串,等于则表示在源数组中能找到尾部与特征字符串相同的数据
                 if ( $tailStr   ==   $t_character )
                    
$ifFound   =   true ;
                
$arr [ ' sortval ' ]         =   $tailStr ; // 写一个可用于排序的元素
                 $arrMySrc []             =   $arr ;
            }
        }
    }
    
    
unset ( $arrChar , $arrSrc );
    
    
if ( $ifFound   ==   false )
    {
        
$arrResult          =   array ( - 1 , ' 没有找到匹配的号码信息! ' );
        
return   $arrResult ;
    }
    
    
// 排序
     usort ( $arrMySrc , ' sort_char_query ' );
    
    
$strHaveChar          =   '' ;
    
// 检查是否为连续号码
     $k      =   0 ;    
    
for ( $i   =   0 , $h   =   0 , $j   =   count ( $arrMySrc );  $i < $j $i ++ )
    {        
        
if ( $i   ==   0 )
        {
            
$strHaveChar      =    $arrMySrc [ $i ][ ' sortval ' ];
            
$arrResult [ $h ++ ]     =   $arrMySrc [ $i ];
            
$k                  =   1 ;
            
continue ;
        }
        
/* if(count($arrResult) == $intLinkNum)
        {
            break;
        }
*/
        
if ( $i   >= 1   &&   $strHaveChar   !=   $arrMySrc [ $i ][ ' sortval ' ]   &&   $strHaveChar + 1   !=   $arrMySrc [ $i ][ ' sortval ' ])
        {
            
// $arrResult        = array();
             $strHaveChar      =    $arrMySrc [ $i ][ ' sortval ' ];
            
// $k                = 1;
        } elseif ( $repeat   &&   $strHaveChar   ==   $arrMySrc [ $i ][ ' sortval ' ])     // 是否可以重复
        {
            
$arrResult [ $h ++ ]     =   $arrMySrc [ $i ];                        
        }        
        
elseif ( $i > 0   &&   $strHaveChar   !=   $arrMySrc [ $i ][ ' sortval ' ])
        {            
            
$strHaveChar      =    $arrMySrc [ $i ][ ' sortval ' ];
            
$arrResult [ $h ++ ]     =   $arrMySrc [ $i ];
            
$k                  =   $k   +   1 ;    
        }
    }
    
    
if ( $k   <   $intLinkNum )
    {
        
$arrResult          =   array ( - 1 , ' 没有找到匹配的号码信息! ' );
    }    
    
return   $arrResult ;    
}
/*
 * add by 20071030 yangxs 自定义二维数组排序函数
 * @param array $arr1 前一数组元素
 * @param array $arr2 当前数组元素
 * @return int  返回是否要交换当前记录与前一记录
*
*/
function  sort_char_query( $arr1 , $arr2 )
{            
    
if  ( $arr1 [ ' sortval ' ==   $arr2 [ ' sortval ' ])  return   0 ;
    
return  ( $arr1 [ ' sortval ' <   $arr2 [ ' sortval ' ] )  ?   - 1   :   1 ;
}

 注释较多,主要是自己以后想用时方便,哈哈,希望各位看官在发现BUG或有什么新想法时不惜告诉我,我的

QQ:75323501

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值