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 相关文章推荐
php5 non-thread-safe和thread-safe这两个版本的区别分析
Mar 13 PHP
PHP中遍历stdclass object的实现代码
Jun 09 PHP
PHPMYADMIN导入数据最大为2M的解决方法
Apr 23 PHP
探讨:如何通过stats命令分析Memcached的内部状态
Jun 14 PHP
PHP禁止个别IP访问网站
Oct 30 PHP
ThinkPHP使用PHPExcel实现Excel数据导入导出完整实例
Jul 22 PHP
php下pdo的mysql事务处理用法实例
Dec 27 PHP
PHP中使用BigMap实例
Mar 30 PHP
thinkphp框架下实现登录、注册、找回密码功能
Apr 06 PHP
thinkPHP框架实现多表查询的方法
Jun 14 PHP
Ubuntu彻底删除PHP7.0的方法
Jul 27 PHP
PHP+iframe模拟Ajax上传文件功能示例
Jul 02 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 mysql数据库操作分页类
2008/06/04 PHP
可输入的下拉框
2006/06/19 Javascript
boxy基于jquery的弹出层对话框插件扩展应用 弹出层选择器
2010/11/21 Javascript
javascript中取前n天日期的两种方法分享
2014/01/26 Javascript
ExtJS4如何给同一个formpanel不同的url
2014/05/02 Javascript
js 获取浏览器版本以此来调整CSS的样式
2014/06/03 Javascript
javascript根据时间生成m位随机数最大13位
2014/10/30 Javascript
JavaScript拖拽、碰撞、重力及弹性运动实例分析
2016/01/08 Javascript
利用JS轻松实现获取表单数据
2016/12/06 Javascript
Vue-Cli中自定义过滤器的实现代码
2017/08/12 Javascript
详解webpack引入第三方库的方式以及注意事项
2019/01/15 Javascript
JavaScript生成一个不重复的ID的方法示例
2019/09/16 Javascript
微信小程序防止多次点击跳转(函数节流)
2019/09/19 Javascript
Vue实现兄弟组件间的联动效果
2020/01/21 Javascript
在实例中重学JavaScript事件循环
2020/12/03 Javascript
跟老齐学Python之玩转字符串(2)
2014/09/14 Python
python 读取.csv文件数据到数组(矩阵)的实例讲解
2018/06/14 Python
利用Pycharm断点调试Python程序的方法
2018/11/29 Python
浅谈Pandas:Series和DataFrame间的算术元素
2018/12/22 Python
使用Python的datetime库处理时间(RPA流程)
2019/11/24 Python
opencv 实现特定颜色线条提取与定位操作
2020/06/02 Python
python3实现语音转文字(语音识别)和文字转语音(语音合成)
2020/10/14 Python
Python Socket多线程并发原理及实现
2020/12/11 Python
美国翻新电子产品商店:The Store
2019/10/08 全球购物
应届生法律顾问求职信
2013/11/19 职场文书
毕业生自荐书模版
2014/01/04 职场文书
考察现实表现材料
2014/05/19 职场文书
班级活动总结格式
2014/08/30 职场文书
迎国庆演讲稿
2014/09/15 职场文书
工会积极分子个人总结
2015/03/03 职场文书
工作简历自我评价
2015/03/11 职场文书
《童年》读后感(三篇)
2019/08/27 职场文书
PhpSpreadsheet中文文档 | Spreadsheet操作教程实例
2021/04/01 PHP
MySQL主从搭建(多主一从)的实现思路与步骤
2021/05/13 MySQL
「女孩的钓鱼慢活」全新版权绘公布
2022/03/21 日漫
python数据处理之Pandas类型转换
2022/04/28 Python