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 相关文章推荐
PHP实现的功能是显示8条基色色带
Oct 09 PHP
MySQL数据库转移,access,sql server 转 MySQL 的图文教程
Sep 02 PHP
php下删除字符串中HTML标签的函数
Aug 27 PHP
php 结果集的分页实现代码
Mar 10 PHP
PHP仿博客园 个人博客(2) 数据库增添改删
Jul 05 PHP
推荐几款用 Sublime Text 开发 Laravel 所用到的插件
Oct 30 PHP
php实现编辑和保存文件的方法
Jul 20 PHP
微信支付PHP SDK之微信公众号支付代码详解
Dec 09 PHP
PHP之将POST数据转化为字符串的实现代码
Nov 03 PHP
如何打开php的gd2库
Feb 09 PHP
Yii 2.0在Grid中格式化时间方法示例
Jun 06 PHP
PHP单例模式与工厂模式详解
Aug 29 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
Symfony2创建基于域名的路由相关示例
2016/11/14 PHP
PHP在弹框中获取foreach中遍历的id值并传递给地址栏
2017/06/13 PHP
浅谈Laravel队列实现原理解决问题记录
2017/08/19 PHP
PHP从零开始打造自己的MVC框架之入口文件实现方法详解
2019/06/03 PHP
JavaScript实际应用:innerHTMl和确认提示的使用
2006/06/22 Javascript
如何让动态插入的javascript脚本代码跑起来。
2007/01/09 Javascript
谷歌浏览器 insertCell与appendChild的区别
2009/02/12 Javascript
js 操作css实现代码
2009/06/11 Javascript
html 锁定页面(js遮罩层弹出div效果)
2009/10/27 Javascript
向左滚动文字 js代码效果
2013/08/17 Javascript
ZeroClipboard插件实现多浏览器复制功能(支持firefox、chrome、ie6)
2014/08/30 Javascript
javascript获取wx.config内部字段解决微信分享
2016/03/09 Javascript
浅谈时钟的生成(js手写简洁代码)
2016/08/20 Javascript
JS实现侧边栏鼠标经过弹出框+缓冲效果
2017/03/29 Javascript
微信小程序 数据遍历的实现
2017/04/05 Javascript
打造通用的匀速运动框架(实例讲解)
2017/10/17 Javascript
vue中Npm run build 根据环境传递参数方法来打包不同域名
2018/03/29 Javascript
React中阻止事件冒泡的问题详析
2019/04/12 Javascript
JS实现根据详细地址获取经纬度功能示例
2019/04/16 Javascript
详解三种方式在React中解决绑定this的作用域问题并传参
2020/08/18 Javascript
python使用自定义user-agent抓取网页的方法
2015/04/15 Python
Python语言描述随机梯度下降法
2018/01/04 Python
ZABBIX3.2使用python脚本实现监控报表的方法
2019/07/02 Python
python 实现多维数组转向量
2019/11/30 Python
Python实现自动访问网页的例子
2020/02/21 Python
Python sklearn库实现PCA教程(以鸢尾花分类为例)
2020/02/24 Python
css3与html5实现响应式导航菜单(导航栏)效果分享
2014/02/12 HTML / CSS
css3的transform中scale缩放详解
2014/12/08 HTML / CSS
Python里面search()和match()的区别
2016/09/21 面试题
2014基层党员干部学习全国两会心得体会
2014/03/17 职场文书
工地标语大全
2014/06/18 职场文书
乡镇八一建军节活动方案
2014/08/24 职场文书
2014年教师节国旗下讲话稿
2014/09/10 职场文书
个人作风纪律整顿整改措施
2014/10/25 职场文书
详解缓存穿透击穿雪崩解决方案
2021/05/28 Redis
通过T-SQL语句创建游标与实现数据库加解密功能
2022/03/16 SQL Server