最近在开始使用 ThinkPHP 5.1 进行一系列开发工做,由于以前是使用 Laravel 进行开发,像是标题中的这种小问题都在 Laravel 中很容易实现。直接使用 array_first 方法进行查找便可。php
可是在 ThinkPHP 中 并无提供相似方法进行快速处理,因此有须要来重复造轮子了?
至此想到的第一个方法就是使用 array_search 不过这个方法中官方提供的方案仅用于简单的一维数组搜索,并且返回的也只是 index 并非找到的结果,淡然经过 index 咱们也能够取出项目来,在 PHP 5.5 带来的新方法 array_column,能够方便的实现二维搜索 在这里的用户笔记 为咱们提供了一个小的示例。laravel
$userdb=Array ( (0) => Array ( (uid) => '100', (name) => 'Sandra Shush', (url) => 'urlof100' ), (1) => Array ( (uid) => '5465', (name) => 'Stefanie Mcmohn', (pic_square) => 'urlof100' ), (2) => Array ( (uid) => '40489', (name) => 'Michael', (pic_square) => 'urlof40489' ) ); $key = array_search(40489, array_column($userdb, 'uid'));
而且赢得了 800+ 的赞扬,到这里可能你会以为 经过这个方式取到 index 而后用 index 取出来就好了。git
可是,若是你再往下翻一下,你会看到另外一条用户笔记 ,这条用户笔记告诉咱们 当咱们使用这种方式来实现二维搜索时你 PHP 版本 必需要在 5.5 + ,做者同时告诉咱们github
Since array_column() will produce a resulting array; it won't preserve your multi-dimentional array's keys. So if you check against your keys, it will fail.
机翻一下 :因为array_column()将产生一个新的数组; 它不会保留多维数组的原来的键。 所以,若是您检查您的键,它将失败。
而后做者也为咱们提供了一个🌰数组
$people = array( 2 => array( 'name' => 'John', 'fav_color' => 'green' ), 5 => array( 'name' => 'Samuel', 'fav_color' => 'blue' ) ); $found_key = array_search('blue', array_column($people, 'fav_color')); // 1 // Here, you could expect that the $found_key would be "5" but it's NOT. It will be 1. Since it's the second element of the produced array by the array_column() function. // 机翻一下:在这里,你预期 $found_key 的将是“5”,但它不是,它将是1.由于它是array_column()函数生成的数组的第二个元素。 // 另外 做者还提到了 // Secondly, if your array is big, I would recommend you to first assign a new variable so that it wouldn't call array_column() for each element it searches. For a better performance, you could do; // 机翻一下:其次,若是您的数组很大,我建议您先分配一个新变量,这样它就不会为它搜索的每一个元素调用array_column()。 为了得到更好的性能,你能够作到; $colors = array_column($people, 'fav_color'); $found_key = array_search('blue', $colors);
看完了这些提示,你已经发现了这其中的坑,然而,这并无结束,由于若是数据不够纯净的话,你用 array_search
实现的功能可能就只局限于 in_array
。
并且,尽管到了这里,还会遇到另一个坑,先看🌰函数
<?php $userdb = array( 0 => array( 'uid' => 100, 'name' => 'Sandra Shush', 'url' => 'urlof100' ), '8' => array( 'uid' => 5465, 'name' => 'Stefanie Mcmohn', 'pic_square' => 'urlof100' ), '3' => Array( // 'uid' => 5555, 'name' => 'Michael', 'pic_square' => 'urlof40489' ), '6' => Array( 'uid' => 40489, 'name' => 'Michael', 'pic_square' => 'urlof40489' ) ); $found_key = array_search(40489, array_column($userdb, 'uid'));
在这里 猜测一下 $found_key 会是什么?答案是: 2
。
??? ,由于当在执行 array_column() 时,第三个元素,也就是键为3的数据中 uid 被注释了,这时候 PHP 就会忽略它,并不会被保留索引位置,因此这时候结果只有 3 个元素,第四个向上替补了,由于数组索引是 0 开始,因此 2 就至关于第 3 个元素了。性能
在 array_search
的用户笔记区中,看到了不少都是数组循环并比对后返回,好比这个,可是这样又遇到一些局限性问题,这时候咱们又想到了 Laravel 中把自主权交给调用者,由调用者在匿名方法内进行处理并返回 bool 值 进行处理。ui
至此,看回 Laravel 的 array_fisrt 方法,经过 Laravel 源码能够看到 array_first 是 Arr::fisrt 方法的一个包装,在这里咱们能够看到 Laravel 的实现方式,在这一小段代码中 还看到了另外一个方法 value(),能够看到,这个方法就是判断是不是一个匿名方法,若是是就执行方法并返回,不是就直接返回。url
public static function first($array, callable $callback = null, $default = null) { if (is_null($callback)) { if (empty($array)) { return value($default); } foreach ($array as $item) { return $item; } } foreach ($array as $key => $value) { if (call_user_func($callback, $value, $key)) { return $value; } } return value($default); } if (! function_exists('value')) { /** * Return the default value of the given value. * * @param mixed $value * @return mixed */ function value($value) { return $value instanceof Closure ? $value() : $value; } }
看到这里,几乎是比较完整的实现,在这里还想到了另一个和助手函数有关的项目:Underscore.php
这是一个 PHP 的方法库,也能够算是是 JS中的 underscore.js
和 loadsh
、ramda
的 PHP 实现。
在这个项目中咱们看到了实现方式.net
public static function find($array, Closure $closure) { foreach ($array as $key => $value) { if ($closure($value, $key)) { return $value; } } return; }
这里的实现更为简单,最终也实现了咱们想要的结果。