2009-05-01 4 views
6

둘 이상의 열에서 다차원 배열 배열을 정렬 할 수 있기를 기대합니다. 더 복잡하게하기 위해 키/열마다 특정 정렬 옵션을 설정할 수 있기를 바랍니다. DB 쿼리의 결과와 비슷하지만 실제 SQL 쿼리 결과가 아니라 SQL 대신 PHP로 정렬 할 필요가 있습니다.지정된 정렬 옵션을 사용하여 두 개 이상의 "열"(키)에 다중 대칭 배열 배열 정렬

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 
     ) 

) 

DB 쿼리로 수행 할 수있는 것과 비슷한 방식으로 정렬 할 수 있기를 바랍니다. 아, 때로는 열/키를 숫자로 지정해야 할 수도 있습니다.

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 : 난 그 이상적으로 생각

$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_multisort($city, SORT_ASC, SORT_STRING, $zip, SORT_DESC, SORT_NUMERIC, $last_name, SORT_ASC, SORT_STRING, $inputArray); 

문제는 거기에 키 이름을 "하드 코딩"하고 싶지 않다는 것입니다. 을 기반으로 솔루션을 만들려고했는데 array_multisort()을 사용하여 array_multisort() 문서에서 문서를 정렬했지만 array_multisort()에 대해 동적으로 작성한 인수 목록을 사용하는 방법을 찾지 못하는 것 같습니다.

내 시도는 배열로 서로를 "체인"그 인수 후

call_user_func_array('array_multisort', $functionArgs); 

당신은 usort를 사용하여 시도 할 가능성이있는

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

답변

1

로부터 지정된 배열입니다. 위의 두 가지 대답은 훌륭하지만 유연한 것도 찾고있었습니다.

확실히 "올바른"대답이 하나 있다고 생각하지 않지만 이것이 내 요구에 적합하고 유연합니다.

당신이 현재 존재하지 않는 것 PHP 설명서에 코멘트에서 적응했다 _usortByMultipleKeys()의 의견에 내 @link에서 볼 수있는,하지만 난 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

나는 하나의 "올바른"답변을 가지고 있지 않다고 동의하지만,이 사실은 예외적으로 인덱스 배열을 정렬해야하며 연관성이없는 배열을 정렬해야한다는 점에서 제 요구 사항에도 매우 가깝습니다. –

+0

이 코드를 사용하여 "경고 : usort() : 배열이 사용자 비교 함수에 의해 수정되었습니다."라는 메시지가 나타납니다. 나는 다음의 설명을 발견하고 그것을 고칠 수있을 때 언급 할 것이다 : http://stackoverflow.com/questions/3235387/usort-array-was-modified-by-the-user-comparison-function – vicenteherrera

1

의 결과이었다. 정렬 자에게 정렬 방법을 알려주는 함수를 작성하면됩니다. 문서에는 그 작업을 수행하는 방법에 대한 자세한 정보가 있습니다.

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의 해결책은이 경우를위한 것입니다. –

4

PHP 5.3에서 call_user_func_array()으로 array_multisort()을 호출 할 때 배열의 모든 매개 변수를 참조해야합니다.

이 함수는 다차원 배열을 정렬하고 올바르게 작동하는 참조 된 매개 변수의 배열을 작성하는 방법을 보여줍니다.

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)