2009-05-01 26 views
6

複数の列の配列を並べ替えることができるようになりました。さらに複雑にするために、キー/列ごとに特定のソートオプションを設定できるようにしたいと考えています。私は、DBクエリの結果と似ているが、実際には1つではないので、SQLではなくPHPでソートする必要がある。指定された並べ替えオプションを使用して2つ以上の "列"(キー)に複数の配列の並べ替えを並べ替え

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:私が思う理想的に、Aという私がで終わるしたい何

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

問題は、そこにキー名を「ハードコード」したくないということです。私はに基づいてソリューションを作成しようとしました。例3 array_multisort()を使用して終了したarray_multisort()のドキュメントからをソートしましたが、array_multisort()の動的に作成された引数リストを使用する方法を見つけることができません。

私の試みは、あなたがusortを使用しようとする場合があります

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

答えて

1

から指定された配列です。上記の両方の答えは良いですが、私は柔軟なものを探していました。

私は間違いなく「正しい」答えがあるとは思っていませんが、これは私のニーズに適しており、柔軟性があります。

あなたはそれが現在存在しているように見えるが、私はhttp://www.php.net/manual/en/function.usort.php#104398は元のコメントの新しいバージョンであるとは考えていないPHPマニュアルでのコメントから適応された_usortByMultipleKeys()のコメントに私の@linkから見ることができるように。私はその新しい提案を使って検討していません。

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

私は1つの "正しい"答えを持っていないことに同意しますが、これは私のニーズにもかなり近くなりますが、インデックス配列をソートする必要があるという例外があります。 –

+0

このコードを使用して、「警告:usort():配列がユーザー比較関数によって変更されました」というメッセージが表示されます。私は次の説明を見つけた、私はそれを修正することができますコメント:http://stackoverflow.com/questions/3235387/usort-array-was-modified-by-the-user-comparison-function – vicenteherrera

1

になり、アレイ、その後

call_user_func_array('array_multisort', $functionArgs); 

に一緒に「チェーン」にこれらの引数ました。ソーターにどのようにソートするかを指示する関数を作成するだけです。ドキュメントには、これを行う方法の詳細があります。

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

あなたはそうのように1行にそれを凝縮できます

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)