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程序的方法
Mar 09 PHP
php图片处理:加水印、缩略图的实现(自定义函数:watermark、thumbnail)
Dec 02 PHP
php curl 伪造IP来源的实例代码
Nov 01 PHP
解析PHP处理换行符的问题 \r\n
Jun 13 PHP
解析PHP跨站刷票的实现代码
Jun 18 PHP
CI框架在CLI下执行占用内存过大问题的解决方法
Jun 17 PHP
PHP获取POST数据的几种方法汇总
Mar 03 PHP
PHP入门教程之使用Mysqli操作数据库的方法(连接,查询,事务回滚等)
Sep 11 PHP
php使用file函数、fseek函数读取大文件效率对比分析
Nov 04 PHP
PHP去除字符串最后一个字符的三种方法实例
Mar 01 PHP
php curl获取到json对象并转成数组array的方法
May 31 PHP
tp5.1 框架路由操作-URL生成实例分析
May 26 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编程实现微信企业向用户付款的方法示例
2017/07/26 PHP
PHP关于foreach复制知识点总结
2019/01/28 PHP
Array对象方法参考
2006/10/03 Javascript
javascript里的条件判断
2007/02/27 Javascript
ArrayList类(增强版)
2007/04/04 Javascript
讨论javascript(一)工厂方式 js面象对象的定义方法
2009/12/15 Javascript
jquery调用wcf并展示出数据的方法
2011/07/07 Javascript
from表单多个按钮提交用onclick跳转不同action
2014/04/24 Javascript
Javascript函数的参数
2015/07/16 Javascript
js焦点文字滚动效果代码分享
2015/08/25 Javascript
JavaScript设置、获取、清除单值和多值cookie的方法
2015/11/17 Javascript
基于Bootstrap+jQuery.validate实现表单验证
2016/05/30 Javascript
jquery.tableSort.js表格排序插件使用方法详解
2020/08/12 Javascript
JavaScript实现动态添加Form表单元素的方法示例
2017/08/14 Javascript
详解vue数组遍历方法forEach和map的原理解析和实际应用
2018/11/15 Javascript
微信小程序实现打卡日历功能
2020/09/21 Javascript
在Vue中使用icon 字体图标的方法
2019/06/14 Javascript
[12:21]VICI vs TNC (BO3)
2018/06/07 DOTA
深入理解python中函数传递参数是值传递还是引用传递
2017/11/07 Python
Python面向对象之继承和组合用法实例分析
2018/08/27 Python
python实现自动登录
2018/09/17 Python
python re库的正则表达式入门学习教程
2019/03/08 Python
python判断正负数方式
2020/06/03 Python
Python 存取npy格式数据实例
2020/07/01 Python
协程Python 中实现多任务耗资源最小的方式
2020/10/19 Python
pytorch中index_select()的用法详解
2021/01/06 Python
德国香水、化妆品和护理产品网上商店:Parfumdreams
2018/09/26 全球购物
彪马加拿大官网:PUMA加拿大
2018/10/04 全球购物
Foot Locker英国官网:美国知名运动产品零售商
2019/02/21 全球购物
大学生毕业求职的自我评价
2013/09/29 职场文书
会计系中文个人求职信
2013/12/24 职场文书
贺卡寄语大全
2014/04/11 职场文书
法制宣传口号
2014/06/16 职场文书
2014年保密工作总结
2014/11/22 职场文书
党员廉洁自律个人总结
2015/02/13 职场文书
拖欠货款起诉状
2015/05/20 职场文书