解析:很简单很基础的题目。如果用库函数,可以很简洁:
<?php function getCountOfStr($string){ $res = str_split($string); $count = array_count_values($res); arsort($count); return $count; } $test_string = "abcdefabceeefffees123"; echo "<pre>"; print_r(getCountOfStr($test_string)); /* * Array( * [e] => 6 * [f] => 4 * [c] => 2 * [a] => 2 * [b] => 2 * [3] => 1 * [2] => 1 * [1] => 1 * [s] => 1 * [d] => 1 *) **/
做一个n位字母的组合功能,例如:给定字母a,b,c则所有非空的非重复组合形式为:{a},{b},{c},{a,b},{a,c},{b,c},{a,b,c}
目标
1.字母所有的非重复组合需要打印出来
3..字母组合要排除,abc(三个字母连续),cba(三个字母倒叙)的情况
解析:全排列和组合的问题已经做过很多次。这里不再做过多解释。
详细的解析见
<?php $a = ''; $b = ""; $c = null; $d = array(); $e = ' '; $f = 0; $g = "0"; var_dump( is_null($a)); var_dump( is_null($b)); var_dump( is_null($c)); var_dump( is_null($d)); var_dump( is_null($e)); var_dump( is_null($f)); var_dump( is_null($g)); var_dump( empty($a)); var_dump( empty($b)); var_dump( empty($c)); var_dump( empty($d)); var_dump( empty($e)); var_dump( empty($f)); var_dump( empty($g)); var_dump( isset($a)); var_dump( isset($b)); var_dump( isset($c)); var_dump( isset($d)); var_dump( isset($e)); var_dump( isset($f)); var_dump( isset($g));
解析:
isset():
is_null():
Returns TRUE
if var
isnull,FALSE
otherwise.也就是只有在变量等于null的时候返回true,其他的如空字符,0,”0“ 等都返回false;
empty():
执行结果:
bool(false) bool(false) bool(true) //is_null除了null返回true,其他的都返回false bool(false) bool(false) bool(false) bool(false) bool(true) bool(true) bool(true) bool(true) bool(false)//empty只要是空,null,false等都返回true.空格串返回false. bool(true) bool(true) bool(true) bool(true) bool(false) //isset检测null或则不存在的变量时返回false.其他的返回true. bool(true) bool(true) bool(true) bool(true)
中文字符串截取可以用mb_substr();
需要注意的是:中文的编码,GBK的编码格式下,一个中文占据两个字节,而在UTF-8编码下,一个汉字占据三个字节。如果不使用库函数截取中文。需要考虑到这一点。
更多解法可见:http://www.qudong.com/soft/program/php/jiqiaoyunyong/20090731/48210.html
无限分类的大致原理是:对于每条元素设置一个唯一的id和一个父类的id. 如此循环下去,可以构成一个庞大的树形结构。用通俗的话说:就好比是文件系统:每个文件都有一个编号和一个父节点。文件夹下面可以新建文件夹。直到叶子节点(文件)。
假设原始数据的结构如下:
$data = array( array('id'=>1,'pid'=>0,'name'=>'我是父节点'), array('id'=>2,'pid'=>1,'name'=>'我是节点1'), array('id'=>3,'pid'=>1,'name'=>'我是节点2'), array('id'=>4,'pid'=>1,'name'=>'我是节点2'), )
则实现无线分类就是基于原始数据的id和pid之间的关系。
<?php function genTree($items,$id='id',$pid='pid',$son = 'children'){ $tree = array(); $tmpMap = array(); foreach ($items as $item) { $tmpMap[$item[$id]] = $item; } foreach ($items as $key => $item) { if (isset($tmpMap[$item[$pid]])) { $tmpMap[$item[$pid]][$son][$key] = &$tmpMap[$key]; } else { $tree[] = &$tmpMap[$item[$id]]; } } unset($tmpMap); return $tree; } $items1 = array( array('id' => 1, 'pid' => 0, 'name' => '一级' ), array('id' => 11, 'pid' => 0, 'name' => '一级' ), array('id' => 2, 'pid' => 1, 'name' => '二级' ), array('id' => 10, 'pid' => 11, 'name' => '二级' ), array('id' => 3, 'pid' => 1, 'name' => '二级' ), array('id' => 12, 'pid' => 11, 'name' => '二级' ), array('id' => 9, 'pid' => 1, 'name' => '二级' ), array('id' => 14, 'pid' => 1, 'name' => '二级' ), array('id' => 4, 'pid' => 9, 'name' => '三级' ), array('id' => 6, 'pid' => 9, 'name' => '三级' ), array('id' => 7, 'pid' => 4, 'name' => '四级' ), array('id' => 8, 'pid' => 4, 'name' => '四级' ), array('id' => 5, 'pid' => 4, 'name' => '四级' ), array('id' => 13, 'pid' => 4, 'name' => '四级' ), array('id' => 15, 'pid' => 8, 'name' => '五级' ), array('id' => 16, 'pid' => 8, 'name' => '五级' ), array('id' => 17, 'pid' => 8, 'name' => '五级' ), array('id' => 18, 'pid' => 16, 'name' => '六级' ), ); echo "<pre>"; echo "父节点:<br/>"; print_r(genTree($items1));
徐祖宁老大给的更加简洁一些:
<?php header("Content-type:text/html;charSet=utf8"); /** * 创建父节点树形数组 * 参数 * $ar 数组,邻接列表方式组织的数据 * $id 数组中作为主键的下标或关联键名 * $pid 数组中作为父键的下标或关联键名 * 返回 多维数组 **/ function find_parent($ar, $id='id', $pid='pid') { foreach($ar as $v) $t[$v[$id]] = $v; foreach ($t as $k => $item){ if( $item[$pid] ){ if( ! isset($t[$item[$pid]]['parent'][$item[$pid]]) ) $t[$item[$id]]['parent'][$item[$pid]] = &$t[$item[$pid]]; } } return $t; } /** * 创建子节点树形数组 * 参数 * $ar 数组,邻接列表方式组织的数据 * $id 数组中作为主键的下标或关联键名 * $pid 数组中作为父键的下标或关联键名 * 返回 多维数组 **/ function find_child($ar, $id='id', $pid='pid') { foreach($ar as $v) $t[$v[$id]] = $v; foreach ($t as $k => $item){ if( $item[$pid] ) { $t[$item[$pid]]['child'][$item[$id]] = &$t[$k]; } } return $t; } $data = array( array('ID'=>1, 'PARENT'=>0, 'NAME'=>'祖父'), array('ID'=>2, 'PARENT'=>1, 'NAME'=>'父亲'), array('ID'=>3, 'PARENT'=>1, 'NAME'=>'叔伯'), array('ID'=>4, 'PARENT'=>2, 'NAME'=>'自己'), array('ID'=>5, 'PARENT'=>4, 'NAME'=>'儿子'), ); $p = find_parent($data, 'ID', 'PARENT'); $c = find_child($data, 'ID', 'PARENT'); echo "<pre>"; echo "父节点:<br/>"; print_r($p); echo "子节点:<br/>"; print_r($c);
题目描述:给定一套系统,系统的目录结构如下:
controller
configs
model
view
www
编写一个classMap类或函数。实现如下功能:
对于controller,configs,model中的类文件做映射。映射的结果为 文件名前缀 ==>相对于www下classMap.php的路径。结果用数组的形式存入map.php中
例如:controller下有三个文件 AdController.php ,loginController.php,UserController.php,configs下有两个文件:SystemConfig.php,AdConfig.php
则最后映射的结果为(注意只map这三个目录controller,configs,model中的文件):
<?php class MapConfig{ public static $configs = array( 'AdController' => '../controller/AdController.php', 'LoginController' => '../controller/LoginController.php', 'UserController' => '../controller/UserController.php', 'SystemConfig' => '../configs/SystemConfig.php', 'UserConfig' => '../configs/configs/UserConfig.php', ) }
看似很简单的一个问题。其实其中考点不少。
目录相关函数,递归的使用(注意三个目录中可能还有其他目录)等。
思路。对于系统的目录,做相应的搜索,如果是文件且在这三个目录中的一个。就对文件位置坐相应映射。如果是目录,继续深层探测。
对于map的结果,可以先用数组保存。最后写入模板文件。
我们做的模板文件内容如下:
<?php class MapConfig{ public static $config={{content}}; }
整体代码如下:
<?php header('Content-Type: text/html; charset=UTF-8'); class ClassMap{ private $configFile = 'Map.php'; private $fileDir = array(); private $passName = array('.','..','view','www','.svn'); private $classPath = array(); public function __Construct($dir){ if(is_array($dir)){ $this->fileDir = $dir; }else{ $this->fileDir = array($dir); } } private function searchClass($parentPath){ $fd = opendir($parentPath); while($path = readdir($fd)){ if(in_array($path,$this->passName)) continue; if(is_dir($parentPath.$path)) $this->searchClass($parentPath.$path.'/'); else{ $temp_path = substr($path,0,strpos($path,'.')); if(!isset($this->classPath[$temp_path])){ $relative_path = str_replace($this->root,"\"/..",$parentPath); $this->classPath[$temp_path] = $relative_path.$path."\""; }else{ echo "文件重复:".$parentPath.$path."<hr>\n"; } } } } public function doSearch(){ foreach($this->fileDir as $v){ $this->root = realpath(dirname(__FILE__).$v); $this->searchClass(realpath(dirname(__FILE__).$v)."/"); } $this->writeFile(); } private function writeFile(){ $content = file_get_contents(dirname(__FILE__).'/Map.php.tpl'); $str = "array(\n"; foreach($this->classPath as $k => $v){ $str.=" '$k' => ".$v.",\n"; } $str.=" )"; $content = str_replace('{{content}}',$str,$content); file_put_contents(dirname(__FILE__).$this->configFile,$content); } } $dir = "/../"; $map = new ClassMap($dir); $map->doSearch(); ?>
(1) 需要处理完整的 html 页面,即不光此 meta 语句
(2) 忽略大小写
(3) ‘ 和 ” 在此处是可以互换的
(4) ‘Content-Type’ 两侧的引号是可以忽略的,但 ‘text/html; charset=gbk’ 两侧的不行
(5) 注意处理多余空格
解析:这里全面考察正则表达式匹配。
(1) 需要处理完整的 html 页面,即不光此 meta 语句 ==》 preg_replace()
(2) 忽略大小写 ==> i修饰符
(3) ‘ 和 ” 在此处是可以互换的 ==》多选结构 【“|‘】
(4) ‘Content-Type’ 两侧的引号是可以忽略的,但 ‘text/html; charset=gbk’ 两侧的不行 ==》可选结构 ’?
(5) 处理多余的空格 \s?表示0到多处空白
综合,我们得到的测试代码如下:(未经测试 :b )
<?php function chgCharSet($url){ $string = getContent($url); $patten = '/(<meta\shttp-equiv\s*=\s*([\'|"]?)Content-Type\2\s*content\s*=\s*([\'|"])text\/html\s*;\s*charset=)([\w]+)(\3\s*>)/i'; preg_replace($patten,"$1"."big5"."$5",$string); } function getContent($url){ return file_get_contents($url); } $url = "http://www.baidu.com"; echo chgCharSet($url);