一覽php數組排序應用攻略「php數組排序方法」

4.2 數組排序

PHP里的數組實際上是一個有序映射。不管是隊列、數組、棧還是字典,在使用PHP編程時,你都可以統一使用PHP的數組類型。這一節,我們只探討關於PHP數組的排序,因為數組的排序是很多項目都會使用到的。雖然數據庫也可以很方便進行排序,但在複雜、動態的業務規則下,更多需要在PHP代碼層進行處理。因此加深對PHP數組的理解,對項目開發將大有禆益。

4.2.1 一道面試題引發的思考

在我當前任職的公司里,有這樣一道面試題,關於數組排序的。簡化和提煉一下,題目是:

請按以下規則,對專輯的歌曲進行排序。
1、按播放次數,從高到低排序。
2、如果播放次數相同,則按收藏人數從高到低排序。
3、如果收藏人數相同,則按下載次數從高到低排序。


並假設有專輯歌曲列表如下:

表4-1 歌曲列表

PHP高級編程-回歸原生態-數組排序

通常,對於這道題,會有三類答案。

第一類,就是一開始就扎進大學時代的排序算法。想着從頭到尾再重新實現一套冒泡排序算法,或者快速排序算法。如果能達到性能最優,並且能準確無誤快速實現也是不錯的做法。但這更多是偏理論化,實際業務需求開發中,很少需要自己再重新實現通用的排序算法。相反,我們只需要能加以使用即可。

所以,第二類答案是,通過最少的代碼,快速實現業務需求。不管你是使用封裝好的第三方開源類庫,還是PHP原生態提供的數組排序函數,只要能實現以上排序規則即可。這時,可以使用array_multisort()函數。這個排序函數功能比較強大,因此理解起來會有點吃力。根據官方文檔的說明,array_multisort() 可以用來一次性對多個數組進行排序,或者根據某一維度或多個維度對多維數組進行排序。

例如,這裡,可以這樣實現:

<?php
// 示例數據
$songs = array(
    array('title' => '恰似你的溫柔', 'play' => 1000, 'like' => 900, 'download' => 800),
    array('title' => '丁香花', 'play' => 2000, 'like' => 700, 'download' => 500),
    array('title' => '突然的自我', 'play' => 2000, 'like' => 800, 'download' => 1300),
    array('title' => '夜空中最亮的星', 'play' => 800, 'like' => 1000, 'download' => 700),);// 初始化輔助數據
$playTimes = $likeTimes = $downloadTimes = array();foreach ($songs as $it) {
    $playTimes[] = $it['play'];
    $likeTimes[] = $it['like'];
    $downloadTimes[] = $it['download'];}// 用一行代碼,根據多維對多維數組進行排序
array_multisort(
    $playTimes, SORT_DESC, SORT_NUMERIC,        // 排序規則1
    $likeTimes, SORT_DESC, SORT_NUMERIC,        // 排序規則2
    $downloadTimes, SORT_DESC, SORT_NUMERIC,    // 排序規則3
    $songs
);


print_r($songs);

最後,運行上面代碼,可以看到結果輸出是:

Array(
    [0] => Array
        (
            

[title]

=> 突然的自我

[play]

=> 2000

[like]

=> 800

[download]

=> 1300 ) [1] => Array (

[title]

=> 丁香花 …… ) [2] => Array (

[title]

=> 恰似你的溫柔 …… ) [3] => Array (

[title]

=> 夜空中最亮的星 …… ))

除開前面的示例數據,中間只需要簡單循環一遍,用於初始化輔助的數據,就可以便捷地實現了上述三個規則的排序。但這還不是最優的。我們再來看下第三類答案。

在揭曉第三類答案之前,我們不妨先簡單來回顧一下以前在中學時代,當遇到求解一元二次(或更高次方)方程式時,當時我們是怎麼解決的?例如這一條方程式:

PHP高級編程-回歸原生態-數組排序

很簡單,我們會先化簡,再求解。即先化簡為我們熟悉的一元一次方程:

PHP高級編程-回歸原生態-數組排序

兩邊求平方根,得到:

PHP高級編程-回歸原生態-數組排序

所以,最後答案是x=3或x=-1。這樣是不是很簡單了?

同樣的道理,如果是對於三維的排序我們很陌生,或者說無從下手,那麼如果這只是一道一維數組的排序呢,我們是不是可以很簡單地處理?

這就是我們所說的,第三類答案——思路最簡單的解決方案。這也是通常所說的降維。有了新的思路,再來解決就不難矣。關鍵點在於,我們要找到一種唯一映射,使得:

PHP高級編程-回歸原生態-數組排序

然後再按照此映射規則,將三維的比較,降為一維的比較,最後再進行數組排序,就能達到同樣的效果。以下是鑒於當前示例數據的參考實現。

<?php
// 三維降一維
$points = array();foreach ($songs as $it) {
    $points[] = 1000000 * $it['play'] + 1000 * $it['like'] + $it['download'];}// 再排序
array_multisort($points, SORT_DESC, SORT_NUMERIC, $songs);

4.2.2 對數組排序的理解

關於PHP數組的排序函數有好幾個,但通常開發同學只記得sort(),ksort(),更多其他的排序函數就記不住,或者沒有印象了。下面將分享如何快速記住這些排序函數的技巧。

從官方文檔摘錄的,對數組排序的函數有:

  • array_multisort()
  • asort()
  • arsort()
  • krsort()
  • ksort()
  • natcasesort()
  • natsort()
  • rsort()
  • shuffle()
  • sort()
  • uasort()
  • uksort()
  • usort()

全部列出來,有13個之多。那怎麼記得住呢?其實,在理科里,都是有技巧的,要靠理解,而非死記硬背。就像數學公式一樣,要活學活用。

我們都知道,PHP數組由鍵和值組成,而排序順序可以是升序,或者是降序。根據這兩個維度,我們可以將上面13個排序函數進行分類。首先分為兩大類:對值排序,和對鍵排序。如下面表格所示。

表4-2 數組排序函數

升序

降序

自定義

自然排序

其他

對值排序

sort()、asort()

rsort()、arsort()

usort()、uasort()

natsort()、natcasesort()

shuffle()、array_multisort()

對鍵排序

ksort()

krsort()

uksort()

對這樣的分類清晰後,接着下再來看怎麼記住這結函數名稱。可以發現,除了隨機排序函數的名稱為shuffle()外,其他全部排序函數都是以“sort()”結尾的。

不難發現,函數名稱中的這些字母表示的意思分別是:

  • k:表示鍵,key的縮寫
  • a:表示鍵值關聯的保持(數字類型的不保持),associative的縮寫
  • r:表示逆向或者翻轉,reverse的縮寫
  • u:表示用戶自定義,user的縮寫

然後,再從最原始的sort()函數開始,若加上首字母a則表示保持索引關係的排序,若加上首字母k則表示對鍵排序。由此構成第一梯度排序函數:

  • sort()、asort()、ksort()

這三個排序函數,若全部在“sort”前加上字母r,則表示降序排序。從而構成第二梯度排序函數:

  • rsort()、arsort()、krsort()

如果在第一梯度的三個排序函數最前面加上首字母u,則更簡單了。直接表示用戶自定義排序系列的函數,即第三梯度排序函數:

  • usort()、uasort()、uksort()

最後,剩下的4個函數排序可歸為第四梯度排序函數,即綜合型的排序,有:

  • natsort()、natcasesort()、shuffle()、array_multisort()

通過這樣的整理,估計你能在更短的時間內,對PHP的數組排序函數有更深刻的理解。甚至乎,可以逐漸明白設計PHP這門語言當時的初衷是多麼的巧妙。

原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/284456.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
投稿專員的頭像投稿專員
上一篇 2024-12-22 15:07
下一篇 2024-12-22 15:07

相關推薦

發表回復

登錄後才能評論