最近在開始使用 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; }
這裏的實現更爲簡單,最終也實現了咱們想要的結果。