2009-05-01 120 views
6

我期望能夠對多個列上的多維數組進行排序。爲了進一步複雜化,我希望能夠爲每個鍵/列設置特定的排序選項。我有什麼是類似於數據庫查詢的結果,但實際上並不是一個來源,因此需要使用PHP而不是SQL進行排序。使用指定的排序選項在多個「列」(鍵)上排列多個多元數組的陣列

Array 
(
    [0] => Array 
     (
      [first_name] => Homer 
      [last_name] => Simpson 
      [city] => Springfield 
      [state] => Unknown 
      [zip] => 66735 
     ) 

    [1] => Array 
     (
      [first_name] => Patty 
      [last_name] => Bouvier 
      [city] => Scottsdale 
      [state] => Arizona 
      [zip] => 85250 
     ) 

    [2] => Array 
     (
      [first_name] => Moe 
      [last_name] => Szyslak 
      [city] => Scottsdale 
      [state] => Arizona 
      [zip] => 85255 
     ) 

    [3] => Array 
     (
      [first_name] => Nick 
      [last_name] => Riviera 
      [city] => Scottsdale 
      [state] => Arizona 
      [zip] => 85255 
     ) 

) 

我希望能夠對它進行排序,類似於可以用數據庫查詢完成的操作。哦,有時一個列/鍵需要用數字來指定。

我腦子裏想的是什麼類似於這樣:

$sortOptions = array(array('city', SORT_ASC, SORT_STRING), 
         array('zip', SORT_DESC, SORT_NUMERIC), 
         array(2, SORT_ASC, SORT_STRING) // 2='last_name' 
        ); 
$sorter = new MultiSort($data, $sortOptions); 
$sortedData = $sorter->getSortedArray() ; 
print_r($jmsSorted); 

我想直到結束是這樣的:

Array 
(
    [0] => Array 
     (
      [first_name] => Nick 
      [last_name] => Riviera 
      [city] => Scottsdale 
      [state] => Arizona 
      [zip] => 85255 
     ) 

    [1] => Array 
     (
      [first_name] => Moe 
      [last_name] => Szyslak 
      [city] => Scottsdale 
      [state] => Arizona 
      [zip] => 85255 
     ) 

    [2] => Array 
     (
      [first_name] => Patty 
      [last_name] => Bouvier 
      [city] => Scottsdale 
      [state] => Arizona 
      [zip] => 85250 
     ) 

    [3] => Array 
     (
      [first_name] => Homer 
      [last_name] => Simpson 
      [city] => Springfield 
      [state] => Unknown 
      [zip] => 66735 
     ) 

) 

更新:我認爲,理想情況下,解決方案將導致動態創建

array_multisort($city, SORT_ASC, SORT_STRING, $zip, SORT_DESC, SORT_NUMERIC, $last_name, SORT_ASC, SORT_STRING, $inputArray); 

問題是我不想在那裏「硬編碼」那些關鍵名稱。我試圖創建一個基於的解決方案示例#3從array_multisort()文檔中排序數據庫結果最終使用array_multisort()但我似乎無法找到一種方法來使用我的動態構建的參數列表array_multisort()

我的嘗試是「連鎖」這些參數組合成一個數組,然後

call_user_func_array('array_multisort', $functionArgs); 

,在一個

Warning: Parameter 2 to array_multisort() expected to be a reference, value given in... 

回答

1

給定的數組這是我最終選擇了能夠多維數組排序。上述兩個答案都很好,但我也在尋找靈活的東西。

我絕對不認爲有任何一個「正確」的答案,但這是什麼適用於我的需求和靈活。

正如你可以從我的@link_usortByMultipleKeys()它改編自PHP手冊,目前似乎並不存在一個評論的評論看,但我相信http://www.php.net/manual/en/function.usort.php#104398是原始評論的新版本。我還沒有探索使用這個新建議。

/** 
* Sort the resultSet. 
* 
* Usage: $sortOptions = array(
*   'section', // Defaults to SORT_ASC 
*   'row' => SORT_DESC, 
*   'retail_price' => SORT_ASC); 
*  $results->sortResults($sortOptions); 
* 
* @param array $sortOptions An array of sorting instructions 
*/ 
public function sortResults(array $sortOptions) 
{ 
    usort($this->_results, $this->_usortByMultipleKeys($sortOptions)); 
} 


/** 
* Used by sortResults() 
* 
* @link http://www.php.net/manual/en/function.usort.php#103722 
*/ 
protected function _usortByMultipleKeys($key, $direction=SORT_ASC) 
{ 
    $sortFlags = array(SORT_ASC, SORT_DESC); 
    if (!in_array($direction, $sortFlags)) { 
     throw new InvalidArgumentException('Sort flag only accepts SORT_ASC or SORT_DESC'); 
    } 
    return function($a, $b) use ($key, $direction, $sortFlags) { 
     if (!is_array($key)) { //just one key and sort direction 
      if (!isset($a->$key) || !isset($b->$key)) { 
       throw new Exception('Attempting to sort on non-existent keys'); 
      } 
      if ($a->$key == $b->$key) { 
       return 0; 
      } 
      return ($direction==SORT_ASC xor $a->$key < $b->$key) ? 1 : -1; 
     } else { //using multiple keys for sort and sub-sort 
      foreach ($key as $subKey => $subAsc) { 
       //array can come as 'sort_key'=>SORT_ASC|SORT_DESC or just 'sort_key', so need to detect which 
       if (!in_array($subAsc, $sortFlags)) { 
        $subKey = $subAsc; 
        $subAsc = $direction; 
       } 
       //just like above, except 'continue' in place of return 0 
       if (!isset($a->$subKey) || !isset($b->$subKey)) { 
        throw new Exception('Attempting to sort on non-existent keys'); 
       } 
       if ($a->$subKey == $b->$subKey) { 
        continue; 
       } 
       return ($subAsc==SORT_ASC xor $a->$subKey < $b->$subKey) ? 1 : -1; 
      } 
      return 0; 
     } 
    }; 
} 
+0

我同意沒有一個「正確」的答案,但補充一點,這與我的需求非常接近,除了例外,我需要對索引數組進行排序,而不是關聯數組。 – 2014-05-07 11:02:33

1

結果你可能想使用usort嘗試。你所要做的就是製作一個函數,告訴分揀機如何對其進行分類。文檔有關於如何做到這一點的更多信息。

3

這應該適用於您描述的情況。

usort($arrayToSort, "sortCustom"); 

function sortCustom($a, $b) 
{ 
    $cityComp = strcmp($a['city'],$b['city']); 
    if($cityComp == 0) 
    { 
     //Cities are equal. Compare zips. 
     $zipComp = strcmp($a['zip'],$b['zip']); 
     if($zipComp == 0) 
     { 
      //Zips are equal. Compare last names. 
      return strcmp($a['last_name'],$b['last_name']); 
     } 
     else 
     { 
      //Zips are not equal. Return the difference. 
      return $zipComp; 
     } 
    } 
    else 
    { 
     //Cities are not equal. Return the difference. 
     return $cityComp; 
    } 
} 

你可以凝結成一條線,像這樣:

function sortCustom($a, $b) 
{ 
    return ($cityComp = strcmp($a['city'],$b['city']) ? $cityComp : ($zipComp = strcmp($a['zip'],$b['zip']) ? $zipComp : strcmp($a['last_name'],$b['last_name']))); 
} 

至於有一個可定製的排序功能,你重新發明輪子。看看array_multisort()函數。

+0

我不同意重新發明輪子。據我所知,如果我想對數據進行排序,就像數據表一樣,按照一列排序,而用另一個排序數據`array_multisort()`不是正確的選擇,因爲它會對每個數據進行排序陣列獨立。我需要他們按照特定的順序排列,具體的方向,我不知道第一手。 crazyj的解決方案就是這種情況。 – 2014-05-07 11:08:58

4

在PHP 5.3中,當調用array_multisort()call_user_func_array()時,數組中的每個參數都必須是一個參考。

此函數對多維數組進行排序並顯示構建可正常工作的引用參數數組的方法。

function msort() 
{ 
    $params = func_get_args(); 
    $array = array_pop($params); 

    if (!is_array($array)) 
    return false; 

    $multisort_params = array(); 
    foreach ($params as $i => $param) 
    { 
    if (is_string($param)) 
    { 
     ${"param_$i"} = array(); 
     foreach ($array as $index => $row) 
     { 
     ${"param_$i"}[$index] = $row[$param]; 
     } 
    } 
    else 
     ${"param_$i"} = $params[$i]; 

    $multisort_params[] = &${"param_$i"}; 
    } 
    $multisort_params[] = &$array; 

    call_user_func_array("array_multisort", $multisort_params); 

    return $array; 
} 

例子:

$的數據是從問題

$sorted_data = msort('city', SORT_ASC, SORT_STRING, 'zip', SORT_DESC, SORT_NUMERIC, $data)