PHP 数组函数妙用

巧妙利用php数组函数,解决二维数组查找问题

问题描述

 最近在开发中遇到一个需求,突发奇想用php数组函数解决,在此记录一下。
 问题简述:假设从数据表中取出所有同学成绩,需要按照如下规则进行查找数据:
  1、找出所有同学中语文成绩最好的同学;
  2、在1的基础上接着找到数学成绩最高的同学;
  3、在2的基础上接着找到英语成绩最高的同学;

解决思路

刚遇到这个需求,第一反应就是不断循环数组进行查找过滤,思路没啥问题就是写出来代码过于丑陋,php毕竟是世界上最好的
语言,不可能没有其他处理办法,终于在一番头脑风暴之后找到下面思路:
 * 利用array_column函数取得所有同学语文成绩;
 * 接着用max函数找到语文最高分;
 * 最后用array_filter过滤出语文最高分的同学们;
 * 循环前三步,即可解决上述问题;

直接上代码

$grades = [
    ['name'=>'姓名一','语文'=>85,'数学'=>99,'英语'=>77],
    ['name'=>'姓名二','语文'=>85,'数学'=>99,'英语'=>77],
    ['name'=>'姓名三','语文'=>99,'数学'=>67,'英语'=>50],
    ['name'=>'姓名四','语文'=>99,'数学'=>67,'英语'=>90],
    ['name'=>'姓名五','语文'=>99,'数学'=>67,'英语'=>90],
    ['name'=>'姓名六','语文'=>99,'数学'=>55,'英语'=>77],
    ['name'=>'姓名七','语文'=>99,'数学'=>55,'英语'=>77],
    ['name'=>'姓名八','语文'=>86,'数学'=>88,'英语'=>90],
    ['name'=>'姓名九','语文'=>86,'数学'=>88,'英语'=>90],
    ['name'=>'姓名十','语文'=>86,'数学'=>88,'英语'=>90],
    ['name'=>'姓名1','语文'=>86,'数学'=>76,'英语'=>77],
    ['name'=>'姓名2','语文'=>86,'数学'=>76,'英语'=>60],
    ['name'=>'姓名3','语文'=>77,'数学'=>76,'英语'=>60],
  ];

  // 找到语文最高分
  $yuwenMax = max(array_column($grades,'语文'));
  $grades = array_filter($grades,function($value) use ($yuwenMax) {
    return $value['语文'] == $yuwenMax;
  });
  // 找到数学最高分
  $shuxueMax = max(array_column($grades,'数学'));
  $grades = array_filter($grades,function($value) use ($shuxueMax) {
    return $value['数学'] == $shuxueMax;
  });
  // 找到英语最高分
  $yingyuMax = max(array_column($grades,'英语'));
  $grades = array_filter($grades,function($value) use ($yingyuMax) {
    return $value['英语'] == $yingyuMax;
  });

进一步精简代码

上述代码中,在找语文、数学、英语最高分的时候,代码基本相同,很容易想到可以用foreach循环处理,使上边的代码进一步简化。

代码如下

$columns = ['语文','数学','英语'];
  foreach ($columns as $column) {
  $max = max(array_column($grades,$column));
  $grades = array_filter($grades,function($value) use ($max,$column) {
     return $value[$column] == $max;
   });
 }
php
本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 4年前 自动加精
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 12
lufeijun1234

@dope2008 正解

5年前 评论

数组排序多个字段啊

5年前 评论
lufeijun1234

@安小游 用array_multisort确实可以实现排序,但是需求是要找出来对应同学。

5年前 评论

只剩下一条数据的时候就可以返回出来了吧,不用继续查找下去了,比如「找出所有同学中语文成绩最好的同学」时就已经只剩下一条数据了的话就不必继续查找了

5年前 评论
lufeijun1234

@xinhuo 恩,正解

5年前 评论
     $sort_all = collect($grades)
            ->sortByDesc('英语')
            ->sortByDesc('数学')
            ->sortByDesc('语文');
        $max_all = $sort_all->where('英语', '=', $sort_all->first()['英语'])
            ->where('数学', '=', $sort_all->first()['数学'])
            ->where('语文', '=', $sort_all->first()['语文'])->all();
        dd($max_all);

        $yuwen_max = collect($grades)->sortByDesc('语文')->first();
        $yuwen_all = collect($grades)->where('语文', '=', $yuwen_max['语文']);

        $shuxue_max = collect($yuwen_all)->sortByDesc('数学')->first();
        $shuxue_all = collect($yuwen_all)->where('数学', '=', $shuxue_max['数学']);

        $yingyu_max = collect($shuxue_all)->sortByDesc('英语')->first();
        $yingyu_all = collect($shuxue_all)->where('英语', '=', $yingyu_max['英语'])->all();
        dd($yingyu_all);

这两种方式也是可以的 不过,使用多个 sort 排序的话,是从后面的有限排序的

5年前 评论

@小龙 这个返回的$max_all和原生的不一样

2 => array:4 [▼
    "name" => "姓名三"
    "语文" => 99
    "数学" => 67
    "英语" => 50
[                       
  3 => [                
    "name" => "姓名四",    
    "语文" => 99,         
    "数学" => 67,         
    "英语" => 90,         
  ],                    
  4 => [                
    "name" => "姓名五",    
    "语文" => 99,         
    "数学" => 67,         
    "英语" => 90,         
  ],                    
]                       
5年前 评论

@lovecn 不会吧?我试了试一样的。$sort_all->first() 得到的是第一名 然后找其他有没有和第一名 一样值的

5年前 评论
lufeijun1234

@lovecn 是不是指数组下标的问题,如果是的话,collect有一个values方法可以重置数组下标

5年前 评论

遇到了一个奇怪的现象,还是作者的那组数据 var_dump() 得到的数正确的结果,可是,如果直接在控制器中 return 得到的却是原数据。很是困惑

file

file

5年前 评论
lufeijun1234

@小龙 敢问,找到原因了么

5年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!