PHP的数组中提高元素查找与元素去重的效率的技巧解析


Posted in PHP onMarch 03, 2016

提高查找数组元素的效率
1.php in_array方法说明

php查找数组元素是否存在,一般会使用in_array方法。

bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] )

参数说明:
needle
待搜索的值,如果needle是字符串,比较是区分大小写的。

haystack
用来比较的数组

strict
如果第三个参数 strict 的值为 TRUE 则 in_array() 函数还会检查 needle 的类型是否和 haystack 中的相同

返回值
如果找到 needle 则返回 TRUE,否则返回 FALSE。

2.in_array查找元素效率

当比较的数组haystack较大时,in_array效率会很低

例子:使用in_array对有10万个元素的数组进行1000次比较

<?php
$arr = array();

// 创建10万个元素的数组
for($i=0; $i<100000; $i++){
  $arr[] = $i;
}

// 记录开始时间
$starttime = getMicrotime();

// 随机创建1000个数字使用in_array比较
for($j=0; $j<1000; $j++){
  $str = mt_rand(1,99999);
  in_array($str, $arr);
}

// 记录结束时间
$endtime = getMicrotime();

echo 'run time:'.(float)(($endtime-$starttime)*1000).'ms<br>';

/**
 * 获取microtime
 * @return float
 */
function getMicrotime(){
  list($usec, $sec) = explode(' ', microtime());
  return (float)$usec + (float)$sec;
}
?>
run time:2003.6449432373ms

使用in_array判断元素是否存在,在10万个元素的数组中比较1000次,运行时间需要约2秒

3.提高查找元素效率方法

我们可以先使用array_flip进行键值互换,然后使用isset方法来判断元素是否存在,这样可以提高效率。

例子:使用array_flip先进行键值互换,再使用isset方法判断,在10万个元素的数组中比较1000次

<?php
$arr = array();

// 创建10万个元素的数组
for($i=0; $i<100000; $i++){
  $arr[] = $i;
}

// 键值互换
$arr = array_flip($arr);

// 记录开始时间
$starttime = getMicrotime();

// 随机创建1000个数字使用isset比较
for($j=0; $j<1000; $j++){
  $str = mt_rand(1,99999);
  isset($arr[$str]);
}

// 记录结束时间
$endtime = getMicrotime();

echo 'run time:'.(float)(($endtime-$starttime)*1000).'ms<br>';

/**
 * 获取microtime
 * @return float
 */
function getMicrotime(){
  list($usec, $sec) = explode(' ', microtime());
  return (float)$usec + (float)$sec;
}
?>
run time:1.2781620025635ms

使用array_flip与isset判断元素是否存在,在10万个元素的数组中比较1000次,运行时间需要约1.2毫秒

因此,对于大数组进行比较,使用array_flip与isset方法会比in_array效率高很多。


快速去重
1.使用array_unique方法进行去重

对数组元素进行去重,我们一般会使用array_unique方法,使用这个方法可以把数组中的元素去重。

<?php
$arr = array(1,1,2,3,3,3,4,4,5,6,6,7,8,8,9,9,9);
$arr = array_unique($arr);
$arr = array_values($arr);
print_r($arr);
?>

输出:

Array
(
  [0] => 1
  [1] => 2
  [2] => 3
  [3] => 4
  [4] => 5
  [5] => 6
  [6] => 7
  [7] => 8
  [8] => 9
)

去重后,键值会不按顺序,可以使用array_values把键值重新排序。

2.使用array_unique方法去重效率

<?php
$arr = array();

// 创建100000个随机元素的数组
for($i=0; $i<100000; $i++){
  $arr[] = mt_rand(1,99);
}

// 记录开始时间
$starttime = getMicrotime();

// 去重
$arr = array_unique($arr);

// 记录结束时间
$endtime = getMicrotime();

$arr = array_values($arr);

echo 'unique count:'.count($arr).'<br>';
echo 'run time:'.(float)(($endtime-$starttime)*1000).'ms<br>';
echo 'use memory:'.getUseMemory();

/**
 * 获取使用内存
 * @return float
 */
function getUseMemory(){
  $use_memory = round(memory_get_usage(true)/1024,2).'kb';
  return $use_memory;
}

/**
 * 获取microtime
 * @return float
 */
function getMicrotime(){
  list($usec, $sec) = explode(' ', microtime());
  return (float)$usec + (float)$sec;
}
?>
unique count:99 
run time:653.39303016663ms 
use memory:5120kb

使用array_unique方法去重,运行时间需要约650ms,内存占用约5m


3.更快的数组去重方法

php有一个键值互换的方法array_flip,我们可以使用这个方法去重,因为键值互换,原来重复的值会变为相同的键。
然后再进行一次键值互换,把键和值换回来则可以完成去重。

<?php
$arr = array();

// 创建100000个随机元素的数组
for($i=0; $i<100000; $i++){
  $arr[] = mt_rand(1,99);
}

// 记录开始时间
$starttime = getMicrotime();

// 使用键值互换去重
$arr = array_flip($arr);
$arr = array_flip($arr);

// 记录结束时间
$endtime = getMicrotime();

$arr = array_values($arr);

echo 'unique count:'.count($arr).'<br>';
echo 'run time:'.(float)(($endtime-$starttime)*1000).'ms<br>';
echo 'use memory:'.getUseMemory();

/**
 * 获取使用内存
 * @return float
 */
function getUseMemory(){
  $use_memory = round(memory_get_usage(true)/1024,2).'kb';
  return $use_memory;
}

/**
 * 获取microtime
 * @return float
 */
function getMicrotime(){
  list($usec, $sec) = explode(' ', microtime());
  return (float)$usec + (float)$sec;
}
?>
unique count:99 
run time:12.840032577515ms 
use memory:768kb

使用array_flip方法去重,运行时间需要约18ms,内存占用约2m

因此使用array_flip方法去重比使用array_unique方法运行时间减少98%,内存占用减少4/5;

PHP 相关文章推荐
BBS(php &amp; mysql)完整版(六)
Oct 09 PHP
PHP编程中八种常见的文件操作方式
Nov 19 PHP
php防盗链的常用方法小结
Jul 02 PHP
PHP用SAX解析XML的实现代码与问题分析
Aug 22 PHP
php strrpos()与strripos()函数
Aug 31 PHP
PHP管理依赖(dependency)关系工具 Composer 安装与使用
Aug 18 PHP
Thinkphp中的curd应用实用要点
Jan 04 PHP
Yii2主题(Theme)用法详解
Jul 23 PHP
使用PHPMailer发送邮件实例
Feb 15 PHP
laravel5.4生成验证码的实例讲解
Aug 05 PHP
PHP有序表查找之插值查找算法示例
Feb 10 PHP
Laravel的Auth验证Token验证使用自定义Redis的例子
Sep 30 PHP
CodeIgniter针对数据库的连接、配置及使用方法
Mar 03 #PHP
CodeIgniter表单验证方法实例详解
Mar 03 #PHP
PHP6新特性分析
Mar 03 #PHP
php轻松实现文件上传功能
Mar 03 #PHP
php编程每天必学之验证码
Mar 03 #PHP
简单介绍PHP非阻塞模式
Mar 03 #PHP
浅析php设计模式之数据对象映射模式
Mar 03 #PHP
You might like
PHP static局部静态变量和全局静态变量总结
2014/03/02 PHP
PHP使用CURL获取302跳转后的地址实例
2014/05/04 PHP
浅谈PHP中output_buffering
2015/07/13 PHP
PHP识别二维码的方法(php-zbarcode安装与使用)
2016/07/07 PHP
PHP判断访客是否手机端(移动端浏览器)访问的方法总结【4种方法】
2019/03/27 PHP
Jquery Uploadify多文件上传带进度条且传递自己的参数
2013/08/28 Javascript
Jquery+asp.net后台数据传到前台js进行解析的方法
2014/05/11 Javascript
JavaScript设计模式之代理模式介绍
2014/12/28 Javascript
Nodejs学习笔记之测试驱动
2015/04/16 NodeJs
javascript拖拽效果延伸学习
2016/04/04 Javascript
第一次接触神奇的Bootstrap表单
2016/07/27 Javascript
Vue数据驱动模拟实现1
2017/01/11 Javascript
基于jQuery实现的打字机效果
2017/01/16 Javascript
win系统下nodejs环境安装配置
2017/05/04 NodeJs
vue 挂载路由到头部导航的方法
2017/11/13 Javascript
超好用的jQuery分页插件jpaginate用法示例【附源码下载】
2018/12/06 jQuery
JS写滑稽笑脸运动效果
2020/05/28 Javascript
javascript实现支付宝滑块验证码效果
2020/07/24 Javascript
[01:43]3.19DOTA2发布会 三代刀塔人第三代
2014/03/25 DOTA
[01:01]青春无憾,一战成名——DOTA2全国高校联赛开启
2018/02/25 DOTA
Python使用chardet判断字符编码
2015/05/09 Python
python 捕获shell脚本的输出结果实例
2017/01/04 Python
Python利用字典将两个通讯录文本合并为一个文本实例
2018/01/16 Python
Python多线程应用于自动化测试操作示例
2018/12/06 Python
python使用PIL模块获取图片像素点的方法
2019/01/08 Python
python 获取毫秒数,计算调用时长的方法
2019/02/20 Python
元组列表字典(莫烦python基础)
2019/04/03 Python
详解利用Python scipy.signal.filtfilt() 实现信号滤波
2019/06/05 Python
pyqt5移动鼠标显示坐标的方法
2019/06/21 Python
Python实现aes加密解密多种方法解析
2020/05/15 Python
python基于exchange函数发送邮件过程详解
2020/11/06 Python
西雅图的买手店:Totokaelo
2019/10/19 全球购物
产假请假条
2014/04/10 职场文书
大学生心理活动总结
2014/07/04 职场文书
城管个人总结
2015/02/28 职场文书
2015初中生物教研组工作总结
2015/07/21 职场文书