2009-05-01 47 views
6

Tôi đang tìm cách sắp xếp một mảng các mảng đa chiều trên nhiều cột. Để làm phức tạp hơn nữa, tôi muốn có thể thiết lập các tùy chọn sắp xếp cụ thể cho mỗi khóa/cột. Tôi có những gì là tương tự như kết quả của một truy vấn DB, nhưng không thực sự đến từ một, do đó cần phải sắp xếp nó trong PHP chứ không phải là SQL.Sắp xếp mảng Mảng đa điểm trên nhiều cột "cột" (khóa) với tùy chọn sắp xếp được chỉ định

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 
     ) 

) 

Tôi muốn có thể sắp xếp nó tương tự như những gì có thể được thực hiện bằng truy vấn DB. Oh, và đôi khi một cột/khóa cần được xác định theo số.

gì tôi nghĩ trong đầu là một cái gì đó tương tự như sau:

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 
     ) 

) 

UPDATE:: Tôi nghĩ rằng lý tưởng, một

$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); 

Những gì tôi muốn kết thúc với điều này là giải pháp sẽ dẫn đến việc tạo động

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

vấn đề là tôi không muốn phải "mã cứng" những tên chính trong đó. Tôi đã thử tạo một giải pháp dựa trên Ví dụ # 3 Sắp xếp kết quả cơ sở dữ liệu từ tài liệu array_multisort() kết thúc bằng cách sử dụng array_multisort() nhưng tôi dường như không thể tìm cách sử dụng danh sách đối số được tạo động của mình cho array_multisort().

nỗ lực của tôi là "chuỗi" những tranh cãi với nhau thành một mảng và sau đó

call_user_func_array('array_multisort', $functionArgs); 

Đó kết quả trong một

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

Trả lời

1

Đây là những gì cuối cùng tôi giải quyết trên để có thể sắp xếp các mảng đa chiều. Cả hai câu trả lời trên đều tốt nhưng tôi cũng đang tìm kiếm một thứ linh hoạt.

Tôi chắc chắn không nghĩ rằng có bất kỳ câu trả lời “đúng” nào, nhưng đây là những gì phù hợp với nhu cầu của tôi và linh hoạt.

Như bạn có thể nhìn thấy từ @link của tôi trong những nhận xét của _usortByMultipleKeys() nó được chuyển thể từ một lời nhận xét trong cuốn hướng dẫn PHP hiện dường như không tồn tại, nhưng tôi tin rằng http://www.php.net/manual/en/function.usort.php#104398 là một phiên bản mới của những nhận xét ban đầu. Tôi đã không khám phá bằng cách sử dụng gợi ý mới đó.

/** 
* 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

Tôi đồng ý không có một câu trả lời "đúng", nhưng darn nó, điều này khá gần với nhu cầu của tôi, ngoại trừ việc tôi cần sắp xếp một mảng được lập chỉ mục, không phải là một mảng kết hợp. –

+0

Tôi nhận được một "Cảnh báo: usort(): Mảng được sửa đổi bởi hàm so sánh người dùng", sử dụng mã này. Tôi đã tìm thấy lời giải thích sau đây, sẽ bình luận khi tôi có thể sửa nó: http://stackoverflow.com/questions/3235387/usort-array-was-modified-by-the-user-comparison-function – vicenteherrera

1

Bạn có thể muốn thử sử dụng usort. Tất cả những gì bạn phải làm là tạo một hàm cho trình phân loại biết cách sắp xếp nó. Các tài liệu có thêm thông tin về cách thực hiện điều đó.

3

Điều này sẽ phù hợp với trường hợp bạn mô tả.

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; 
    } 
} 

Bạn có thể ngưng tụ thành một dòng như vậy:

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']))); 
} 

Như xa như có một chức năng sắp xếp tùy biến, bạn đang reinventing the wheel. Hãy xem hàm array_multisort().

+0

Tôi không đồng ý trên reinventing the wheel. Theo như tôi có thể nói, nếu tôi muốn sắp xếp dữ liệu, như bảng dữ liệu, nơi tôi sắp xếp theo một cột và sắp xếp dữ liệu theo một cột khác, 'array_multisort()' KHÔNG phải là lựa chọn đúng, vì nó sắp xếp từng mảng độc lập. Tôi cần chúng được sắp xếp theo một thứ tự cụ thể, hướng cụ thể, mà tôi không biết trước tiên. Giải pháp của Crazyj là giải pháp cho trường hợp này. –

4

Trong PHP 5.3, mọi thông số trong mảng phải là tham chiếu khi gọi array_multisort() với call_user_func_array().

Hàm này sắp xếp một mảng đa chiều và hiển thị một cách để tạo một mảng tham số tham chiếu hoạt động chính xác.

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; 
} 

Ví dụ:

$ dữ liệu là mảng được từ câu hỏi

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