这几天一直在做一个需求,要求找出数据库相连的电话号码,相连的号码要求可以是前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