zoukankan      html  css  js  c++  java
  • 妙用PHP函数处理数组

    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 获得当前单元(当前单元默认为数组第一个成员)的键名,此时的键名即是原数组的值重复次数最多的值。

  • 相关阅读:
    uva 10791 Minimum Sum LCM
    欧拉函数
    uva 10820 Send a Table
    本原勾股数组(PPT)
    uva 10003 Cutting Sticks
    生成随机数据
    uva 10759 Dice Throwing
    uva 106 Fermat vs. Pythagoras
    WPF 与 摄像头资料
    纠结于wpf 多国语言方案,希望各位指点
  • 原文地址:https://www.cnblogs.com/niuben/p/12459146.html
Copyright © 2011-2022 走看看