2011-06-29 38 views
2

我需要實現一些特定的排序算法。我有兩個數組:如何按數組定義的特定順序對大量項目進行排序?

$items = array(
    array("id" => "…", "type" => "alpha"), 
    array("id" => "…", "type" => "beta"), 
    array("id" => "…", "type" => "company"), 
    array("id" => "…", "type" => "marketing"), 
    array("id" => "…", "type" => "beta"), 
    array("id" => "…", "type" => "company"), 
    array("id" => "…", "type" => "alpha"), 
    array("id" => "…", "type" => "alpha"), 
    array("id" => "…", "type" => "company"), 
    array("id" => "…", "type" => "marketing"), 
    […] 
); 

$order = array("company", "marketing", "alpha", "beta"); 

正如你propably可以想像,我需要根據$order指定的順序進行排序$items

+1

「$ items」從哪裏來?如果他們來自數據庫,你不能直接在查詢過程中對它們進行排序(使用'ORDER BY')嗎? – KingCrunch

+0

我並不是真的來自我目前工作時的數據庫。我寧願有一個函數'orderByArray($ items,$ order)'。然而,我可以很容易地編輯查詢......有沒有辦法,例如。'ORDER type BY(「company」,「marketing」,「alpha」,「beta」)'? –

+0

'ORDER BY'公司'ORDER BY'營銷''等等。 – KingCrunch

回答

3

可以使用usort

usort($items, "cmp"); 

function cmp($a, $b) 
{ 
    $order = array("company" => 0, "marketing" => 1, "alpha" => 2, "beta" => 3); 

    $order_a = $order[$a["type"]]; 
    $order_b = $order[$b["type"]]; 

    if ($order_a == $order_b) { 
    return 0; 
    } 
    return ($order_a < $order_b) ? -1 : 1; 
} 
+0

這裏的所有答案都可以工作,但是由於這讓我明白瞭如何使用usort,所以我將其標記爲答案(因爲我的代碼現在大部分都是這個)。 –

4

運行通過$items並使用「類型」作爲關鍵字將所有內容編入索引。然後運行$order並查找與該「類型」對應的項目列表,並將它們追加到排序列表中。運行於O(n+k),k爲|order|

+0

O(n + k),k是#order :) – duedl0r

+0

因此編輯:) – Patrick

+0

愛這種解決方案的平凡瑣碎的感覺。 :D –

1

使用usort,這是高效的PHP算法,並且可以根據您提供的條件運行。

http://php.net/manual/en/function.usort.php

這裏是一個正在運行的代碼,你可以基準它爲您的數據: http://codepad.org/MRpZQkKk

,如果你想改變排序指標分析這會給你更多的控制權, 也複雜明智的相當快,應該是O(n log n)(內部快速排序), ,空間複雜度也低。

這裏更多的是對的: Which sort algorithms does PHP's usort apply?

<?php 

    $items = array(
     array("id" => "…", "type" => "alpha"), 
     array("id" => "…", "type" => "beta"), 
     array("id" => "…", "type" => "company"), 
     array("id" => "…", "type" => "marketing"), 
     array("id" => "…", "type" => "beta"), 
     array("id" => "…", "type" => "company"), 
     array("id" => "…", "type" => "alpha"), 
     array("id" => "…", "type" => "alpha"), 
     array("id" => "…", "type" => "company"), 
     array("id" => "…", "type" => "marketing"), 

    ); 

    $order = array("company", "marketing", "alpha", "beta"); 

    $orderIndexes = array(); /* cache indexes of the order keys */ 
    for($i = 0 ; $i < count($order) ; $i++) 
    { 
     $orderIndexes[$order[$i]] = $i ; 
    } 


    /* we have something like : 
    $orderIndexes = array('company' => 0 , 'marketing' => 1 , ....); 
    */ 



    function myCriteria($item1,$item2) /* this is the function used to decide order */ 
    { global $orderIndexes; 
     $index1 = $orderIndexes[$item1['type']]; 
     $index2 = $orderIndexes[$item2['type']]; 

     return $index1 - $index2 ; // negative means $item1 precedes $item2 

    } 

usort($items,"myCriteria"); 
print_r($items); 

?> 
1

你可以做一個天真的實現用戶的排序功能:

function mySort($a, $b) { 
    global $order; 

    return array_search($a['type'], $order) - array_search($b['type'], $order); 
} 

然後做一個usort()

usort($items, 'mySort'); 

可能效率不高,但它是works


UPDATE
爲了避免多次調用array_search()您可以翻轉$order陣列一次事前。這將用一個簡單的查找替換array_search()

$reversed_order = array_flip($order); 

function mySort($a, $b) { 
    global $reversed_order; 

    return $reversed_order[$a['type']] - $reversed_order[$b['type']]; 
} 

應該更加高效。 (demo

+0

它有多高效? – duedl0r

+0

@ duedl0r我認爲不如在數據庫中排序那麼高效。除此之外,很難說沒有數據大小等的指示。數組查找[看起來是'O(1)'](http://stackoverflow.com/questions/5641052/time-space-complexity- of-php-array),所以更新的解決方案可能比第一個更好。 (畢竟是這個意圖)。 – jensgram

+0

@ duedl0r另外,'usort()'可能是[quicksort](http://en.wikipedia.org/wiki/Quicksort),就像['sort() '](http://php.net/manual/en/function.sort.php)。 – jensgram

2

非常相似,與Özgür的自定義比較函數進行排序!但是,我會構建功能來處理未按順序考慮的意外值。他們放置在排序數組的末尾。

usort($items,"compare"); 
echo "<pre>"; 
print_r($items); 
echo "</pre>"; 

function compare($a, $b) { 
    $order = array("company" => 1, "marketing" => 2, "alpha" => 3, "beta" => 4); 
    $ax = $order[$a['type']]; $bx = $order[$b['type']];  
    if ($ax < 1) return 1; 
    if ($ax == $bx) return 0; 
    return ($ax > $bx) ? 1 : -1; 
} 
相關問題