PHP 的数组是一种很强大的数据类型,与此同时 PHP 内置了一系列与数组相关的函数可以很轻易的实现日常开发的功能。但是我发现好像很多小伙伴都忽略了内置函数的作用(比如我自己就编写过一些有关数组操作的代码然后发现PHP自带了/(ㄒoㄒ)/~~),善用 PHP 内置函数能极大的提高开发效率和运行效率(内置函数都是用 C 写的效率比用 PHP 写的高很多),所以本文便总结了一些在常见场景中利用 PHP 内置函数的实现方法。此外如果想更深入的学习有关 PHP 数组函数最好还是去查 PHP 手册!点我看官方数组函数手册

取指定键名

对于某些关联数组,有时候我们只想取指定键名的那部分,比如数组为 ['id' => 1, 'name' => 'zane', 'password' => '123456'] 此时若只想取包含 id 和 name 的部分该怎么实现呢?下面直接贴代码。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

<?php

$raw = ['id' => 1, 'name' => 'zane', 'password' => '123456'];

// 自己用 PHP 实现

function onlyKeys($raw, $keys) {

    $new = [];

    foreach ($raw as $key => $val) {

        if (in_array($key, $keys)) {

            $new[$key] = $val;

        }

    }

    

    return $new;

}

// 用 PHP 内置函数实现

function newOnlyKeys($array, $keys) {

    return array_intersect_key($array, array_flip($keys));

}

var_dump(onlyKeys($raw, ['id', 'name']));

// 结果 ['id' => 1, 'name' => 'zane']

var_dump(newOnlyKeys($raw, ['id', 'name']));

// 结果 ['id' => 1, 'name' => 'zane']

很明显简洁很多有木有!不过 array_intersect_key 和 array_flip 是什么鬼?这里简单的介绍一下这两个函数的作用,首先是 array_flip 函数,这个函数的功能是「将数组的键和值对调」,也就是键名变成值,值变成键名。我们传递的 $keys 参数经过这个函数便从 [0 => 'id', 1 => 'name'] 转变为了 ['id' => 0, 'name' => 1]。这样做的目的是为了向 array_intersect_key 函数服务,array_intersect_key 函数的功能是「使用键名比较计算数组的交集」,也就是返回第一个参数数组中与其他参数数组相同键名的值。这样便实现了取指定键名的功能 ~(≧▽≦)/~啦!当然要详细了解这两个函数的功能还是要查 PHP 官方手册:array_flip array_intersect_key

移除指定键名

有了上一个例子做铺垫,这个就简单讲讲啦,道理是大同小异滴。

1

2

3

4

5

6

7

8

9

<?php

$raw = ['id' => 1, 'name' => 'zane', 'password' => '123456'];

// 用 PHP 内置函数实现

function removeKeys($array, $keys) {

    return array_diff_key($array, array_flip($keys));

}

// 移除 id 键

var_dump(removeKeys($raw, ['id', 'password']));

// 结果 ['name' => 'zane']

和上一个例子相比本例只是将 array_intersect_key 函数改为 array_diff_key,嗯……相信大家能猜出来这个函数的功能「使用键名比较计算数组的差集」,刚好和 array_intersect_key 的功能相反而已。官方手册:array_diff_key

数组去重

这个相信大家都有这个需求,当然 PHP 也内置了 array_unique 函数供给大家使用,如下例:

1

2

3

4

5

<?php

$input = ['you are' => 666, 'i am' => 233, 'he is' => 233, 'she is' => 666];

$result = array_unique($input);

var_dump($result);

// 结果 ['you are' => 666, 'i am' => 233]

嘿,用这个函数就能解决大部分问题了,但是有时候你可能会觉得它不够快,原因如下:

array_unique() 先将值作为字符串排序,然后对每个值只保留第一个遇到的键名,接着忽略所有后面的键名。

因为这个函数会先将数组进行排序,所以速度可能在某些场景达不到预期的要求。

现在我们可以祭出我们的黑科技 array_flip 函数,众所周知 PHP 里数组的键名是唯一的,所以在键名和值对调后重复的值便被忽略了。试想一下我们连续调用两次 array_flip 函数是不是就相当于实现了 array_unique 函数的功能呢?示例代码如下:

1

2

3

4

5

<?php

$input = ['you are' => 666, 'i am' => 233, 'he is' => 233, 'she is' => 666];

$result = array_flip(array_flip($input));

var_dump($result);

// 结果 ['she is' => 666, 'he is' => 233]

嗯哼?!结果和 array_unique 的不一样!为什么,我们可以从 PHP 官方手册得到答案:

如果同一个值出现多次,则最后一个键名将作为它的值,其它键会被丢弃。

总的来说就是 array_unique 保留第一个出现的键名,array_flip 保留最后一个出现的键名。

注意:使用 array_flip 作为数组去重时数组的值必须能够作为键名(即为 string 类型或 integer 类型),否则这个值将被忽略。

此外,若不需要保留键名我们可以直接这样使用 array_values(array_flip($input))

0x04 重置索引

当我们想要对一个索引并不连续的数组进行重置时,比如数组:[0 => 233, 99 => 666],对于这种数组我们只需要调用 array_values 函数即可实现。如下例:

1

2

3

4

<?php

$input = [0 => 233, 99 => 666];

var_dump(array_values($input));

// 结果 [0 => 233, 1 => 66]

需要注意的是 array_values 函数并不止重置数字索引还会将字符串键名也同样删除并重置。那如何在保留字符串键名的同时重置数字索引呢?答案就是 array_slice 函数,代码示例如下:

1

2

3

4

<?php

$input = ['hello' => 'world', 0 => 233, 99 => 666];

var_dump(array_slice($input, 0));

// 结果 ['hello' => 'world', 0 => 233, 1 => 66]

array_slice 函数的功能是取出数组的中的一段,但它默认会重新排序并重置数组的数字索引,所以可以利用它重置数组中的数字索引。

清除空值

嘿,有时候我们想清除某个数组中的空值比如:nullfalse00.0[]空数组''空字符串'0'字符串0 ,这时 array_filter 函数便能帮上大忙。代码如下:

1

2

3

4

<?php

$input = ['foo', false, -1, null, '', []];

var_dump(array_filter($input));

// 结果 [0 => 'foo', 2 => -1]

为什么会出现这样的结果捏?array_filter 的作用其实是「用回调函数过滤数组中的单元」,它的第二个参数其实是个回调函数,向数组的每个成员都执行这个回调函数,若回调函数的返回值为 true 便保留这个成员,为 false 则忽略。这个函数还有一个特性就是:

如果没有提供 callback 函数, 将删除 array 中所有等值为 FALSE 的条目。

等值为 false 就是转换为 bool 类型后值为 false 的意思,详细看文档:转换为布尔类型。

注意:如果不填写 callback 函数,00.0'0'字符串0 这些可能有意义的值会被删除。所以如果清除的规则有所不同还需要自行编写 callback 函数。

确认数组成员全部为真

有时候我们希望确认数组中的的值全部为 true,比如:['read' => true, 'write' => true, 'execute' => true],这时我们需要用一个循环判定吗?NO,NO,NO……只需要用 array_product 函数便可以实现了。代码如下:

1

2

3

4

5

6

7

<?php

$power = ['read' => true, 'write' => true, 'execute' => true];

var_dump((bool)array_product($power));

// 结果 true

$power = ['read' => true, 'write' => true, 'execute' => false];

var_dump((bool)array_product($power));

// 结果 false

为什么能实现这个功能呢? array_product 函数本来的功能是「计算数组中所有值的乘积」,在累乘数组中所有成员的时候会将成员的值转为数值类型。当传递的参数为一个 bool 成员所组成的数组时,众所周知 true 会被转为 1,false 会被转为 0。然后只要数组中出现一个 false 累乘的结果自然会变成 0,然后我们再将结果转为 bool 类型不就是 false 了嘛!

注意:使用 array_product 函数将在计算过程中将数组成员转为数值类型进行计算,所以请确保你了解数组成员转为数值类型后的值,否则会产生意料之外的结果。比如:

1

2

3

4

<?php

$power = ['read' => true, 'write' => true, 'execute' => 'true'];

var_dump((bool)array_product($power));

// 结果 false

上例是因为 'true' 在计算过程中被转为 0。要想详细了解请点击这里。

获取指定键名之前 / 之后的数组

如果我们只想要关联数组中指定键名值之前的部分该怎么办呢?又用一个循环?当然不用我们可以通过 array_keys、array_search 和 array_slice 组合使用便能够实现!下面贴代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

<?php

$data = ['first' => 1, 'second' => 2, 'third' => 3];

function beforeKey($array, $key) {

    $keys = array_keys($array);

      // $keys = [0 => 'first', 1 => 'second', 2 => 'third']

    $len = array_search($key, $keys);

    return array_slice($array, 0, $len);

}

var_dump(beforeKey($data, 'first'));

// 结果 []

var_dump(beforeKey($data, 'second'));

// 结果 ['first' => 1]

var_dump(beforeKey($data, 'third'));

// 结果 ['first' => 1, 'second' => 2]

思路解析,要实现这样的功能大部分同学都应该能想到 array_slice 函数,但这个函数取出部分数组是根据偏移量(可以理解为键名在数组中的顺序,从 0 开始)而不是根据键名的,而关联数组的键名却是是字符串或者是不按顺序的数字,此时要解决的问题便是「如何取到键名对应的偏移量?」,这是 array_keys 函数便帮了我们大忙,它的功能是「返回数组中部分的或所有的键名」默认返回全部键名,此外返回的键名数组是以数字索引的,也就是说返回的键名数组的索引就是偏移量!例子中的原数组变为: [0 => 'first', 1 => 'second', 2 => 'third'] 。然后我们通过 array_search 便可以获得指定键名的偏移量了,因为这个函数的功能是「在数组中搜索给定的值,如果成功则返回首个相应的键名」。有了偏移量我们直接调用 array_slice 函数便可以实现目的了。

上面的例子懂了,那获取指定键名之后的数组也就轻而易举了,略微修改 array_slice 即可。直接贴代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

<?php

$data = ['first' => 1, 'second' => 2, 'third' => 3];

function afterKey($array, $key) {

    $keys = array_keys($array);

    $offset = array_search($key, $keys);

    return array_slice($array, $offset + 1);

}

var_dump(afterKey($data, 'first'));

// 结果 ['second' => 2, 'third' => 3]

var_dump(afterKey($data, 'second'));

// 结果 ['third' => 3]

var_dump(afterKey($data, 'third'));

// 结果 []

那如何获取指定值之前或之后的数组呢?嘿,记得 array_search 的作用吧,其实我们只需要这样调用 beforeKey($data, array_search($value, $data)) 不就实现了嘛!

数组中重复次数最多的值

敲黑板,划重点!据说这是一道面试题喔。假设有这样一个数组 [6, 11, 11, 2, 4, 4, 11, 6, 7, 4, 2, 11, 8],请问如何获取数组中重复次数最多的值?关键就在于 array_count_values 函数。实例代码如下:

1

2

3

4

5

6

7

8

<?php

$data = [6, 11, 11, 2, 4, 4, 11, 6, 7, 4, 2, 11, 8];

$cv = array_count_values($data);

// $cv = [6 => 2, 11 => 4, 2 => 2, 4 => 3, 7 => 1, 8 => 1]

arsort($cv);

$max = key($cv);

var_dump($max);

// 结果 11

array_count_values 函数的功能是「统计数组中所有的值」,就是将原数组中的值作为返回数组的键名,值出现的次数作为返回数组的值。这样我们便可以通过 arsort 函数对出现的次数进行降序排序并且保持索引关联。最后使用 key 获得当前单元(当前单元默认为数组第一个成员)的键名,此时的键名即是原数组的值重复次数最多的值。

总结

虽然 PHP 提供了很多和数组相关的函数,但使用起来还是不算太方便而且都是通过函数的调用方式而没有面向对象相关的实现,所以我最近在写一个开源的工具类项目 zane/utils,封装了一些常用的方法并且支持链式调用,其中的 Ary 类实现 「获取数组中重复次数最多的值」只需一行,如下所示:

1

2

3

4

$data = [6, 11, 11, 2, 4, 4, 11, 6, 7, 4, 2, 11, 8];

$max = Ary::new($data)->countValues()->maxKey();

var_dump($max);

// 结果 1

php数组函数有哪些操作?php数组函数的应用的更多相关文章

  1. Python笔记-built-in函数,文件操作,lambda函数

    Built-In: i = abs(123) print(i) j = abs(-123) print(j)#123#123 #all,需要传一个可迭代的东西,里面所有的值是真,返回真 r1 = al ...

  2. php数组使用技巧及操作总结

    数组,可以说是PHP的数据应用中较重要的一种方式.PHP的数组函数众多,下面是一些小结,借此记之,便于以后鉴之. 1. 数组定义 数组的定义使用 array()方式定义,可以定义空数组:<?ph ...

  3. 数组转集合、集合转数组、字符串数组与int型、long型数组等的转换

    在项目中经常会遇到数组转集合.集合转数组.数组之间类型转换等操作 1.数组转集合 为了实现把一个数组转换成一个ArrayList,很多Java程序员会使用如下的代码: String str[] = { ...

  4. array_reduce方法用回调函数迭代地将对数组的值进行操作

    在处理php数组的时候,有一种需求特别的频繁,如下二维数组: $arr = array( 1=>array( 'id' => 5, 'name' => '张三' ), 2=>a ...

  5. 操作 numpy 数组的常用函数

    操作 numpy 数组的常用函数 where 使用 where 函数能将索引掩码转换成索引位置: indices = where(mask) indices => (array([11, 12, ...

  6. php数组键值操作和数组统计函数-函数

    1.数组函数//作用:提供了很多官方写的很多有用的代码段,提高编写速度 1)数组的键值操作函数 array_values();//获取数组中的值 array_keys();//获取数组中的键 in_a ...

  7. 函数bsxfun,两个数组间元素逐个计算的二值操作

    转自http://www.cnblogs.com/rong86/p/3559616.html 函数功能:两个数组间元素逐个计算的二值操作 使用方法:C=bsxfun(fun,A,B) 两个数组A合B间 ...

  8. php重建二叉树(函数缺省参数相关的都写在后面,比如array_slice函数中的$length属性,故第一个参数是操作的数组)

    php重建二叉树(函数缺省参数相关的都写在后面,比如array_slice函数中的$length属性,故第一个参数是操作的数组) 一.总结 牛客网和洛谷一样,是真的好用 二.php重建二叉树 输入某二 ...

  9. JQuery操作类数组的工具方法

    JQuery学习之操作类数组的工具方法 在很多时候,JQuery的$()函数都返回一个类似数据的JQuery对象,例如$('div')将返回div里面的所有div元素包装的JQuery对象.在这中情况 ...

随机推荐

  1. c# 状态机实现

    c#仿boost statechart的状态机.去年转到unity使用c#,statechart原来的风格蛮爽的,缺点是编译忒慢,在c#则编译根本不是问题. 不一样的地方首先是简单!因为没做一些东西如 ...

  2. Java继承(上)

    继承的定义 在人类生活中的学徒关系,父子关系等等都属于继承: 但是在程序中是一种类与类的关系 在程序中可以使用父类的方法,也可以添加自己的方法,但是不能选择的继承,要继承就需要把所有的特点全部继承下来 ...

  3. 黄聪:windows下使用xampp3.2.2配置多个监听端口和不同的网站目录

    windows下使用xampp3.2.2配置多个监听端口和不同的网站目录 一:配置Apache文件httpd.conf 打开Apache的配置文件httpd.conf,可以通过点击xampp的Apac ...

  4. awk字符串操作(字符串链接、传入传出shell变量)

    1.awk基础 awk的环境变量及其意义   https://blog.csdn.net/snowpay/article/details/52451718 linux awk命令详解 https:// ...

  5. 关于x-shell连接不上本地虚拟机linux

    首先把虚拟机网络模式调成nat模式,用于共享主机的ip地址. 然后再虚拟机输入命令ifconfig查看虚拟机的ip 在windows下ping一下虚拟机的ip确保能ping通,同理在虚拟机下ping主 ...

  6. java的反射机制之getDeclaredMethods和getMethods的区别

    getMethods()  返回一个包含某些 Method 对象的数组,这些对象反映此 Class 对象所表示的类或接口(包括那些由该类或接口声明的以及从超类和超接口继承的那些的类或接口)的公共 me ...

  7. tensorflow实战系列(四)基于TensorFlow构建AlexNet代码解析

    整体流程介绍: 我们从main函数走,在train函数中,首先new了一个network;然后初始化后开始训练,训练时设定设备和迭代的次数,训练完后关闭流程图. 下面看network这个类,这个类有许 ...

  8. ubuntu16下用QT5实现对话框应用

    ubuntu16下用QT5,实现对话框程序,步骤:生成界面Dialog.ui,将它应用到主程序,通过主程序显示. 一 界面练习 1 Dialog.ui界面生成 在命令行输入:designer 进入界面 ...

  9. python中的异常处理常用方法

    异常处理 什么是异常? 异常就是与正常情况不同,程序在执行过程中出现错误,导致无法执行完毕.异常其实就是代码执行过程中出错. 常见的一些异常 AttributeError 试图访问一个对象没有的属性, ...

  10. Microsoft DQS sqlException 0x80131904 - SetDataQualitySessionPhaseTwo

    遇到这个问题的原因可以从报错信息看出来,大概率是.net framework的问题 可以尝试如下解决途径 1. regenerate .net Assemble for DQS 2. 如果步骤一无法解 ...