PHP的数组是一种很强大的数据类型,与此同时PHP内置了一系列与数组相关的函数可以轻松地实现日常开发功能。

1. 取数组指定键名列

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

<?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_flip 函数,这个函数的功能是「将数组的键和值对调」,也就是键名变成值,值变成键名。我们传递的 $keys 参数经过这个函数便从 [0 => 'id', 1 => 'name'] 转变为了 ['id' => 0, 'name' => 1]。

这样做的目的是为了向 array_intersect_key 函数服务,array_intersect_key 函数的功能是「使用键名比较计算数组的交集」,也就是返回第一个参数数组中与其他参数数组相同键名的值。

这样便实现了取指定键名的功能

2. 移除数组中指定键名

有了上一个例子做铺垫,这个就很简单了

<?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 的功能相反而已。

3. 数组去重

PHP内置了array_unique函数

<?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_filp函数,这个函数的功能是「将数组的键和值对调」。试想一下我们连续调用两次 array_flip 函数是不是就相当于实现了 array_unique 函数的功能呢?

<?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 类型),否则这个值将被忽略。

4. 重置数组索引

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

<?php
$input = [0 => 233, 99 => 666];
var_dump(array_values($input));
// 结果 [0 => 233, 1 => 66]

需要注意的是 array_values 函数并不止重置数字索引还会将字符串键名也同样删除并重置。

那如何在保留字符串键名的同时重置数字索引呢?答案就是 array_slice 函数,代码示例如下:

<?php
$input = ['hello' => 'world', 0 => 233, 99 => 666];
var_dump(array_slice($input, 0));
// 结果 ['hello' => 'world', 0 => 233, 1 => 66]

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

5. 清除数组中空值

有时候我们想清除某个数组中的空值比如:null、false、0、0.0、[]空数组、''空字符串、'0'字符串0 ,这时 array_filter 函数便能帮上大忙。

<?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 函数,0、0.0、'0'字符串0 这些可能有意义的值会被删除。所以如果清除的规则有所不同还需要自行编写 callback 函数。

6. 确定数组成员全部为真

有时候我们希望确认数组中的的值全部为 true,比如:

['read' => true, 'write' => true, 'execute' => true]

这时我们需要用一个循环判定吗?NO,NO,NO……只需要用 array_product 函数便可以实现了。

<?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 函数将在计算过程中将数组成员转为数值类型进行计算,所以请确保你了解数组成员转为数值类型后的值,否则会产生意料之外的结果。

比如:

<?php
$power = ['read' => true, 'write' => true, 'execute' => 'true'];
var_dump((bool)array_product($power));
// 结果 false

上例是因为 'true' 在计算过程中被转为 0。

7. 获取数组指定键名之前或之后的数组

如果我们只想要关联数组中指定键名值之前的部分该怎么办呢?又用一个循环?

当然不用我们可以通过 array_keys、array_search 和 array_slice 组合使用便能够实现!

<?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 即可。

<?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)) 就实现了

8. 统计出数组中重复次数最多的值

假设有这样一个数组 [6, 11, 11, 2, 4, 4, 11, 6, 7, 4, 2, 11, 8],请问如何获取数组中重复次数最多的值?关键就在于 array_count_values 函数。

<?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函数处理数组的更多相关文章

  1. 转:函数指针数组的妙用(I)

    转自:http://blog.sina.com.cn/s/blog_4c78b35f010008hi.html 笔者在开发某软件过程中遇到这样一个问题,前级模块传给我二进制数据,输入参数为 char* ...

  2. C++基础——函数指针 函数指针数组

    ==================================声明================================== 本文版权归作者所有. 本文原创,转载必须在正文中显要地注明 ...

  3. typedef 函数指针 数组 std::function

    1.整型指针 typedef int* PINT;或typedef int *PINT; 2.结构体 typedef struct { double data;}DATA,  *PDATA;  //D ...

  4. C++程序设计(关于函数中数组传递的一点心得)

    题目: 10个学生考完期末考试评卷完成后,老师需要划出及格线,要求如下: (1) 及格线是10的倍数: (2) 保证至少有60%的学生及格: (3) 如果所有的学生都高于60分,则及格线为60分:   ...

  5. C#委托与C语言函数指针及函数指针数组

    C#委托与C语言函数指针及函数指针数组 在使用C#时总会为委托而感到疑惑,但现在总新温习了一遍C语言后,才真正理解的委托. 其实委托就类似于C/C++里的函数指针,在函数传参时传递的是函数指针,在调用 ...

  6. PHP中使用数组指针函数操作数组示例

    数组的内部指针是数组内部的组织机制,指向一个数组中的某个元素.默认是指向数组中第一个元素通过移动或改变指针的位置,可以访问数组中的任意元素.对于数组指针的控制PHP提供了以下几个内建函数可以利用. ★ ...

  7. C/C++ 一段代码区分数组指针|指针数组|函数指针|函数指针数组

    #include<stdio.h> #include<stdlib.h> #include<windows.h> /* 举列子说明什么是函数指针 */ //以一个加 ...

  8. C/C++ 不带参数的回调函数 与 带参数的回调函数 函数指针数组 例子

    先来不带参数的回调函数例子 #include <iostream> #include <windows.h> void printFunc() { std::cout<& ...

  9. c语言函数传递数组

    1.传递数组,打印不出来 #include <stdio.h> void solve() { printf(]); } int main() { int i; ;i<n;i++) { ...

  10. Linux C 程序 函数,数组,指针,gdb调试器(SEVEN)

    函数,数组,指针,gdb调试器 1.函数定义 如果明确指定返回类型,默认为int 参数传递:实参对形参的参数传递是单向的,实参只是把自己的值赋给形参.                      形参的 ...

随机推荐

  1. JVM实战—3.JVM垃圾回收的算法和全流程

    大纲 1.JVM内存中的对象何时会被垃圾回收 2.JVM中的垃圾回收算法及各算法的优劣 3.新生代和老年代的垃圾回收算法 4.避免本应进入S区的对象直接升入老年代 5.Stop the World问题 ...

  2. [转]OpenCV_Find Basis F-Matrix and computeCorrespondEpilines(获取一对图像的基础矩阵及对应极线)

    代码如下: // BasisMatrixCalculate.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <ios ...

  3. 一种调试 线段树 / Treap / Splay / 左偏树 / LCT 等树形结构的技巧

    前言 如果我们需要观察程序运行过程中,某一个变量.某一个序列的变化情况,你可以在修改的地方打断点 debug,或者直接在需要的地方输出就行了. 但是对于一些树形结构,我们不好将其直观地呈现出来,常常只 ...

  4. 测试直播伴侣和OBS对透明度的支持哪个好?

    测试直播伴侣和OBS对透明度的支持哪个好? 抖音无人直播,用抖音弹幕助手 测试直播伴侣和OBS对透明度的支持哪个好?抖音无人直播,用抖音弹幕助手 ​测试地址1 ​测试地址2

  5. 引发类型为“System.Windows.Forms.AxHost+InvalidActiveXStateException”的异常 解决办法

    出现题目的异常,多是引用第三方控件引起的. 在NEW时,需要初始化该对象. AxESACTIVEXLib.AxESActiveX ax = new AxESACTIVEXLib.AxESActiveX ...

  6. 单点登录-OAuth2

    单点登录的实现原理 单点登录在现在的系统架构中广泛存在,他将多个子系统的认证体系打通,实现了一个入口多处使用,而在架构单点登录时,也会遇到一些小问题,在不同的应用环境中可以采用不同的单点登录实现方案来 ...

  7. linux安装软件配置

    CentOS7更换yum为阿里源 1 备份本地源mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backu ...

  8. w3cschool-MyBatis 教程

    参考 https://www.w3cschool.cn/mybatis/mybatis-dyr53b5w.html MyBatis 入门 SqlSessionFactoryBuilder用 SqlSe ...

  9. linux:lamp环境

    关于LAMP LAMP搭建 安装php和Apache 先装php,因为安装php有apache的依赖包 yum install php 启动Apache service httpd start 启动成 ...

  10. NOIp 2024 考试策略

    无论简不简单,都要在前 30min 浏览所有题面,思考哪题可做.哪题不可做,思考能打哪些部分分,9:00 再开始写 T1. 题目简单时 9:00 开写后,30min 以内切完 T1. 9:30 开 T ...