专栏首页硬核项目经理的专栏PHP中比较数组的时候发生了什么?

PHP中比较数组的时候发生了什么?

PHP中比较数组的时候发生了什么?

首先还是从代码来看,我们通过比较运算符号来对两个数组进行比较:

1var_dump([1, 2] == [2, 1]); // false
2
3var_dump([1, 2, 3] > [3, 2, 1]); // false
4
5var_dump([5, 6, 7] > [1, 2, 3, 4]); // false

第一组:仔细看,从一眼看过去的正常角度来说,代码中对比的数组其实是一样的数组,[1, 2]和[2, 1]都是两个包含两个元素的数组,元素内容也是一样的,但是,他们的位置不一样。 第二组:同样是位置不一样,[1, 2, 3]是小于[3, 2, 1]的 第三组:[5, 6, 7]每个元素都大于[1, 2, 3, 4],但结果是没有后一个数组大。

相信不少同学已经看出一些端倪了。数组之间的操作符比较是先进行元素数量对比,然后再对比每个键值。官方文档上的解释为:

具有较少成员的数组较小,如果运算数 1 中的键不存在于运算数 2 中则数组无法比较,否则挨个值比较

 1<?php
 2// 数组用标准比较运算符这样比较的
 3function standard_array_compare($op1, $op2)
 4{
 5    if (count($op1) < count($op2)) {
 6        return -1; // $op1 < $op2
 7    } elseif (count($op1) > count($op2)) {
 8        return 1; // $op1 > $op2
 9    }
10    foreach ($op1 as $key => $val) {
11        if (!array_key_exists($key, $op2)) {
12            return null; // uncomparable
13        } elseif ($val < $op2[$key]) {
14            return -1;
15        } elseif ($val > $op2[$key]) {
16            return 1;
17        }
18    }
19    return 0; // $op1 == $op2
20}

上述代码就是php中使用比较操作符进行数组比较时的代码,首先是count数组的元素数量,如果数组1大于数组2就返回1,否则返回-1。如果相等的话,遍历每一个元素进行对比,如果数组1的某个键值不存在在数组2中,返回null,如果数组1的某个键的值大于数组2的这个键的值,返回1,否则返回-1。遍历的元素也都相同的情况下,最后返回0表示相等。

使用普通的比较操作符对比键值对形式的数组效果会好一些,因为是以固定的键来进行比对,不是以数组下标:

1var_dump(['a'=>1, 'b'=>2] == ['b'=>2, 'a'=>1]); // ture
2var_dump(['a'=>1, 'b'=>2] == ['a'=>2, 'b'=>1]); // false
3
4
5var_dump(['a' => 1, 'b' => 5] < ['a' => 2, 'b' => 1]); // true

注意第三条比较,我们的第一个数组的b元素是大于第二个数组的,但通过上面的数组比较代码可以看出,当第一个元素比较结果已经出现了大于小于的情况时,直接就return返回了结果,后面的元素不会再进行比较了。

那么多维数组呢?

1var_dump([['aa' => 1], ['bb' => 1, 'dd'=>2]] == [['aa' => 2], ['bb' => 1]]); // false
2var_dump([['aa' => 1], ['bb' => 1, 'dd'=>2]] < [['aa' => 2], ['bb' => 1]]); // true
3var_dump([['aa' => 1], ['bb' => 1, 'dd'=>2]] < [['aa' => 1, 'cc' => 1], ['bb' => 1]]); // true

子数组会递归进行比较,比较规则依然是按照默认的数组操作符比较方式进行。

弄清楚了数组的比较是如何进行的,那么问题来了,假设前端传给我们的数据是这样的:

1[
2    'John',
3    '178cm',
4    '62kg',
5]

而我们数据库里存的是:

1[
2    '62kg',
3    'John',
4    '178cm',
5]

这时如果直接比对两个数组内容,或者直接用json字符串比对,他们都是不相同的,这可怎么办呢?试试自定义一个对比方法吧!

 1function array_equal($a, $b)
 2{
 3    return (is_array($a) && is_array($b) && array_diff($a, $b) === array_diff($b, $a));
 4}
 5
 6$arr1 = [
 7    'John',
 8    '178cm',
 9    '62kg',
10];
11$arr2 = [
12    '62kg',
13    'John',
14    '178cm',
15];
16
17var_dump(array_equal($arr1, $arr2)); // true
18
19// 元素不一样的话
20$arr2 = [
21    '62kg',
22    'John Jobs',
23    '178cm',
24];
25var_dump(array_equal($arr1, $arr2)); // false
26
27// 再弄乱一点
28$arr1 = [
29    [
30        '55kg',
31        'Bob',
32        '172cm',
33        [
34            'employee',
35        ],
36    ],
37    [
38        'John',
39        '178cm',
40        '62kg',
41        [
42            'manager',
43        ],
44    ],
45];
46$arr2 = [
47    [
48        '62kg',
49        'John',
50        '178cm',
51        [
52            'manager',
53        ],
54    ],
55    [
56        [
57            'employee',
58        ],
59        '55kg',
60        '172cm',
61        'Bob',
62
63    ],
64];
65var_dump(array_equal($arr1, $arr2)); // true

其实就是利用了array_diff()这个函数,它的作用是取两个数组的差集,然后再对比两个数组差集的结果来判断两个数组是否相等。这个方法适用于下标数组的比对,但不适用于键值对数组的比对,array_diff()只是取值的差集结果集,不会比对键,所以对于键值对的数组直接使用比较操作符就好啦!

对于数组的比较我们只要弄清楚它的原理就可以了,如果原理不清楚很可能就会埋下隐藏的BUG。数组的比较一定要记住这三点:

1.先比较元素数量

2.再比较每一个元素(多维数组递归比较)

3.先后顺序,第一个有比较结果了后面就不会继续比较了,全部都相等才会返回相等

测试代码:https://github.com/zhangyue0503/dev-blog/blob/master/php/201910/source/PHP%E4%B8%AD%E6%AF%94%E8%BE%83%E6%95%B0%E7%BB%84%E7%9A%84%E6%97%B6%E5%80%99%E5%8F%91%E7%94%9F%E4%BA%86%E4%BB%80%E4%B9%88%EF%BC%9F.php

参考链接:https://www.php.net/manual/zh/language.operators.comparison.php

本文分享自微信公众号 - 硬核项目经理(fullstackpm),作者:ZyBlog

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-12-02

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • PHP中用+号连接数组的结果是?

    我们在开发中,有时候会将两个数组合并连接起来,这个时候要注意了,千万不要偷懒直接使用+号哦,为什么呢?我们看看以下代码:

    硬核项目经理
  • PHP编程

    2.可变参数:func_get_args()、func_num_args()、fund_get_arg(argument_number)

    硬核项目经理
  • 微服务:从设计到部署【笔记】

    一、微服务简介 A.单体地狱 1.成功的应用有一个趋势,随着时间推移而变得越来越臃肿 2.复杂的单体应用本身就是持续部署的障碍 3.单体应用使得采用新框架和语言...

    硬核项目经理
  • 程序猿修仙之路--数据结构之你是否真的懂数组?

    但凡IT江湖侠士,算法与数据结构为必修之课。早有前辈已经明确指出:程序=算法+数据结构 。要想在之后的江湖历练中通关,数据结构必不可少。数据结构与算法相辅相成...

    架构师修行之路
  • 程序猿修仙之路--数据结构之你是否真的懂数组?

    但凡IT江湖侠士,算法与数据结构为必修之课。早有前辈已经明确指出:程序=算法+数据结构 。要想在之后的江湖历练中通关,数据结构必不可少。数据结构与算法相辅相成...

    心莱科技雪雁
  • [jQuery学习系列二 ]2-JQuery学习二-数组操作

    一枝花算不算浪漫
  • Numpy 简介

    NumPy是Python中科学计算的基础软件包。 它是一个提供多了维数组对象,多种派生对象(如:掩码数组、矩阵)以及用于快速操作数组的函数及API, 它包括...

    iOSDevLog
  • 数组方法整理

    mcq
  • Day 1-Java-imooc-5.数组

    课程地址:http://www.imooc.com/learn/85 总结图片来自 http://www.imooc.com/article/10535 ? -...

    杨熹
  • 图解算法系列(三):数组

    "数组"结构其实就是一排紧密相邻的可数内存,并提供了一个能够直接访问单一的数据内容的计算方法.我们其实可以想象一下自家的信箱,每一个信箱都有住址,其中路名就是名...

    公众号---志学Python

扫码关注云+社区

领取腾讯云代金券