在PHP中,數組排序是數據處理中的常見操作,尤其在面對多維數組或者需要多條件排序的場景時,選擇合適的排序函數尤為重要。 arsort()和ksort()是兩個經常被聯合使用的函數,通過它們的組合,可以實現對數組的值和鍵進行有序管理。本文將結合具體代碼示例,詳細講解這兩個函數如何联合使用以實現多條件排序。
arsort() :對數組進行降序排序,保留鍵名,按“值”排序。
ksort() :對數組按“鍵”進行升序排序,保留鍵值。
雖然這兩個函數本質上是分別作用於“值”和“鍵”的排序,但在某些場景中,可以通過聯合使用它們,實現更靈活的多條件排序邏輯。
假設有如下一個數組,表示多個用戶的得分記錄:
<span><span><span class="hljs-variable">$users</span></span><span> = [
</span><span><span class="hljs-string">'user3'</span></span><span> => [</span><span><span class="hljs-string">'score'</span></span><span> => </span><span><span class="hljs-number">85</span></span><span>, </span><span><span class="hljs-string">'time'</span></span><span> => </span><span><span class="hljs-number">120</span></span><span>],
</span><span><span class="hljs-string">'user1'</span></span><span> => [</span><span><span class="hljs-string">'score'</span></span><span> => </span><span><span class="hljs-number">92</span></span><span>, </span><span><span class="hljs-string">'time'</span></span><span> => </span><span><span class="hljs-number">110</span></span><span>],
</span><span><span class="hljs-string">'user2'</span></span><span> => [</span><span><span class="hljs-string">'score'</span></span><span> => </span><span><span class="hljs-number">85</span></span><span>, </span><span><span class="hljs-string">'time'</span></span><span> => </span><span><span class="hljs-number">100</span></span><span>],
</span><span><span class="hljs-string">'user4'</span></span><span> => [</span><span><span class="hljs-string">'score'</span></span><span> => </span><span><span class="hljs-number">92</span></span><span>, </span><span><span class="hljs-string">'time'</span></span><span> => </span><span><span class="hljs-number">130</span></span><span>],
];
</span></span>
現在的需求是:
首先按得分(score)降序排序;
若得分相同,則按完成時間(time)升序排序;
若得分和時間都相同,再按用戶名(鍵名)升序排序。
為了實現複雜排序,可以使用uasort()結合自定義函數:
<span><span><span class="hljs-title function_ invoke__">uasort</span></span><span>(</span><span><span class="hljs-variable">$users</span></span><span>, function(</span><span><span class="hljs-variable">$a</span></span><span>, </span><span><span class="hljs-variable">$b</span></span><span>) {
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$a</span></span><span>[</span><span><span class="hljs-string">'score'</span></span><span>] == </span><span><span class="hljs-variable">$b</span></span><span>[</span><span><span class="hljs-string">'score'</span></span><span>]) {
</span><span><span class="hljs-keyword">if</span></span><span> (</span><span><span class="hljs-variable">$a</span></span><span>[</span><span><span class="hljs-string">'time'</span></span><span>] == </span><span><span class="hljs-variable">$b</span></span><span>[</span><span><span class="hljs-string">'time'</span></span><span>]) {
</span><span><span class="hljs-keyword">return</span></span><span> </span><span><span class="hljs-number">0</span></span><span>; </span><span><span class="hljs-comment">// 留待後續使用ksort處理鍵名排序</span></span><span>
}
</span><span><span class="hljs-keyword">return</span></span><span> (</span><span><span class="hljs-variable">$a</span></span><span>[</span><span><span class="hljs-string">'time'</span></span><span>] < </span><span><span class="hljs-variable">$b</span></span><span>[</span><span><span class="hljs-string">'time'</span></span><span>]) ? -</span><span><span class="hljs-number">1</span></span><span> : </span><span><span class="hljs-number">1</span></span><span>; </span><span><span class="hljs-comment">// 時間升序</span></span><span>
}
</span><span><span class="hljs-keyword">return</span></span><span> (</span><span><span class="hljs-variable">$a</span></span><span>[</span><span><span class="hljs-string">'score'</span></span><span>] > </span><span><span class="hljs-variable">$b</span></span><span>[</span><span><span class="hljs-string">'score'</span></span><span>]) ? -</span><span><span class="hljs-number">1</span></span><span> : </span><span><span class="hljs-number">1</span></span><span>; </span><span><span class="hljs-comment">// 得分降序</span></span><span>
});
</span></span>
由於uasort()不影響鍵名的順序,我們可以再用ksort()來對鍵名進行排序,但這一步只有在值相同時才有意義。可以利用中間轉換結構:
<span><span><span class="hljs-comment">// 將排序後的數組按鍵重新分組</span></span><span>
</span><span><span class="hljs-variable">$temp</span></span><span> = [];
</span><span><span class="hljs-keyword">foreach</span></span><span> (</span><span><span class="hljs-variable">$users</span></span><span> </span><span><span class="hljs-keyword">as</span></span><span> </span><span><span class="hljs-variable">$key</span></span><span> => </span><span><span class="hljs-variable">$value</span></span><span>) {
</span><span><span class="hljs-variable">$groupKey</span></span><span> = </span><span><span class="hljs-variable">$value</span></span><span>[</span><span><span class="hljs-string">'score'</span></span><span>] . </span><span><span class="hljs-string">'-'</span></span><span> . </span><span><span class="hljs-variable">$value</span></span><span>[</span><span><span class="hljs-string">'time'</span></span><span>];
</span><span><span class="hljs-variable">$temp</span></span><span>[</span><span><span class="hljs-variable">$groupKey</span></span><span>][</span><span><span class="hljs-variable">$key</span></span><span>] = </span><span><span class="hljs-variable">$value</span></span><span>;
}
</span><span><span class="hljs-comment">// 對每組鍵名排序</span></span><span>
</span><span><span class="hljs-keyword">foreach</span></span><span> (</span><span><span class="hljs-variable">$temp</span></span><span> </span><span><span class="hljs-keyword">as</span></span><span> &</span><span><span class="hljs-variable">$group</span></span><span>) {
</span><span><span class="hljs-title function_ invoke__">ksort</span></span><span>(</span><span><span class="hljs-variable">$group</span></span><span>); </span><span><span class="hljs-comment">// 鍵名升序</span></span><span>
}
</span><span><span class="hljs-comment">// 合併成最終結果</span></span><span>
</span><span><span class="hljs-variable">$final</span></span><span> = [];
</span><span><span class="hljs-keyword">foreach</span></span><span> (</span><span><span class="hljs-variable">$temp</span></span><span> </span><span><span class="hljs-keyword">as</span></span><span> </span><span><span class="hljs-variable">$group</span></span><span>) {
</span><span><span class="hljs-keyword">foreach</span></span><span> (</span><span><span class="hljs-variable">$group</span></span><span> </span><span><span class="hljs-keyword">as</span></span><span> </span><span><span class="hljs-variable">$k</span></span><span> => </span><span><span class="hljs-variable">$v</span></span><span>) {
</span><span><span class="hljs-variable">$final</span></span><span>[</span><span><span class="hljs-variable">$k</span></span><span>] = </span><span><span class="hljs-variable">$v</span></span><span>;
}
}
</span></span>
此時, $final就是我們期望的,按照score 降序、time 升序、鍵名升序排列的結果。
在實際項目中,也可以將數據拍平、引入排序權重,結合array_multisort()來操作,但這種方法對保持鍵名不太友好。聯合使用arsort和ksort的方式,則可以保留關聯數組的完整結構和鍵名。
arsort()和ksort()本身並不能直接支持多條件排序,但通過分組處理與多步排序邏輯,結合uasort()等函數,可以靈活地實現類似SQL 中的ORDER BY col1 DESC, col2 ASC的效果。掌握這些排序技巧,有助於開發者在處理複雜數組數據時更加得心應手。