0

サブ配列内にある値で配列をソートする必要があるというトリッキーな状況にありますが、結果をステージングする必要があります。つまり、並べ替えは 1 つまたは複数の優先順位で行う必要があります。

問題は、並べ替えプロセス全体がユーザーによって構成可能であるため、何かをハードコーディングするオプションがないことです。柔軟性を維持する必要がありますが、事前定義された並べ替え機能を提供することでオプションを制限しています。

始めましょう:

この例では、印刷形式のリストを並べ替えます。可能なプロパティを 2 つだけ使用します。

ユーザーは、INI ファイルで並べ替えプロセスを構成します。

sort_priority="special_deal:desc,ratio:asc"

説明:

// special_deal -> This is a binary flag - if set to 1 the print format is a special deal and should therefore be presented first
// ratio -> This is the ratio of the given print format (i.e. 0.75 (that's a 3:4 format) or 1 (that's a 1:1 format))

コードでは、構成が分割されています。

$toSort=array(<OUR ARRAY WE WANT TO SORT>);

$sortKeys=explode(',', 'special_deal:desc,ratio:asc');

// we then iterate through the defined keys
foreach($sortKeys as $sortKey){

     // we put together the name of the predefined sort function
     if(strstr($sortKey, ':')) {
         list($skey,$sdir)=explode(':', $sortKey);
         $methodName='sort_by_'.$skey.'_'.$sdir;
     } else $methodName='sort_by_'.$sortKey.'_asc';

     // so $methodName can (for instance) be: sort_by_special_deal_asc
     // or: sort_by_ratio_desc

     // if the sort function is available, we apply it
     if(is_callable($methodName))
         usort($toSort, $methodName);
}

並べ替え関数は次のようになります。

function sort_by_special_deal_asc($a, $b){
    return ($a['specialDeal']!=$b['specialDeal']);
}
function sort_by_special_deal_desc($a, $b){
    return ($a['specialDeal']==$b['specialDeal']);
}
function sort_by_ratio_asc($a, $b){
    if($a==$b) return 0;
    return $a['ratio']<$b['ratio'] ? -1 : 1;
}
function sort_by_ratio_desc($a, $b){
    if($a==$b) return 0;
    return $a['ratio']>$b['ratio'] ? -1 : 1;
}

当面の問題について...

上記のソリューションは正常に機能しますが、最後に適用された並べ替え機能に対してのみです。そのため、適用される並べ替え関数を反復処理すると、usort()を呼び出すたびに、配列内のすべての要素が並べ替えられます。問題は、並べ替えをステージング (またはスタック) する必要があるため、この例では、実際には次のことを意味します。

1.) Sort all entries so that the ones that are a special deal come first
2.) Then sort all entries by their ratio

データがどのように見えるかの例を次に示します。

$formats=array(
     array(
         'format' => '30x40',
         'ratio' => 0.75
     ),
     array(
         'format' => '60x90',
         'ratio' => 0.667
     ),
     array(
         'format' => '50x50',
         'ratio' => 1
     ),
     array(
         'format' => '60x80',
         'ratio' => 0.75,
         'specialDeal' => 1
     )
);

上記のソート機能を使用すると、望ましい結果は次のようになります。

$formats=array(
     array(
         'format' => '60x80',
         'ratio' => 0.75,
         'specialDeal' => 1
     ),
     array(
         'format' => '60x90',
         'ratio' => 0.667
     ),
     array(
         'format' => '30x40',
         'ratio' => 0.75
     ),
     array(
         'format' => '50x50',
         'ratio' => 1
     ),
);

これで問題が適切に説明されることを願っています。

ここで誰かが私を正しい方向に向けることができますか? usort()を使用して、せいぜい動的にこれを達成するにはどうすればよいですか?

ありがとう!

編集:注意してください-私の比較関数(上記を参照)に問題がありました。次の 2 つの問題がありました。

1.) ブール値を返すのが間違っていました - -1、0、または 1 を返すのが正しい方法でした。2.) 完全な配列/オブジェクトとしての $a と $b の比較は正しくありませんでした。正しいのは、これらの配列内の特定の値 (関数が比較す​​ることになっている値) を比較することです。

詳細については、受け入れられた回答とそれに応じたコメントセクションを参照してください。

4

2 に答える 2

1

ユーザーの並べ替え設定を解析して、次のような配列を作成します。

$sortMethods = array('sort_by_ratio_desc', 'sort_by_special_deal_asc');

次に、次のような比較を使用して並べ替えます。

usort($array, function ($a, $b) use ($sortMethods) {
    foreach ($sortMethods as $method) {
        $result = $method($a, $b);
        if ($result != 0) {
            break;
        }
    }
    return $result;
});
于 2013-03-21T10:55:54.780 に答える
0

php.net マニュアルの uasort のコメントを確認してください - http://php.net/manual/en/function.uasort.php

具体的には、dholmes によって投稿された動的コールバックを持つものです。

于 2013-03-21T11:01:33.250 に答える