個人的には、カスタム (匿名) 関数を と組み合わせて使用しusort()
ます。
編集:再 - あなたのコメント。うまくいけば、これが正しい軌道に乗るでしょう。この関数は、EN を持つ要素または EN を持たない要素に同等の優先度を与えるか、EN を持つ要素が 1 つだけの場合に優先度を調整します。
usort($array,function ($a, $b) {
$ac = strpos($a['countries'],'EN');
$bc = strpos($b['countries'],'EN');
if (($ac !== false && $bc !== false) || ($ac == false && $bc == false)) {
return 0;
}
elseif ($ac !== false) {
return 1;
}
else {
return -1;
}
});
一方、この関数は、両方が EN を持っている場合は同等の優先度を与え、一方が EN を持っている場合は優先度を高くし、どちらも EN を持っていない場合はテキスト比較を行います。
usort($array,function ($a, $b) {
$ac = strpos($a['countries'],'EN');
$bc = strpos($b['countries'],'EN');
if ($ac !== false && $bc !== false)) {
return 0;
}
elseif ($ac !== false) {
return 1;
}
elseif ($bc !== false) {
return -1;
}
else {
if ($a['countries'] == $b['countries']) {
return 0;
}
elseif($a['countries'] > $b['countries']) {
return 1;
}
else {
return -1;
}
}
});
繰り返しますが、うまくいけば、これがあなた自身で前進するのに十分な方向性を与えるでしょう. 問題が発生した場合は、お気軽にコメントを投稿してください。私がお手伝いします。 複数のプロパティを重みで比較する場合の注意: ファンキーなスイッチ ブロックを試してください。
$ac = array_flip(explode(',',$a['countries']));
$bc = array_flip(explode(',',$b['countries']));
switch (true) {
case array_key_exists('EN',$ac) && !array_key_exists('EN',$bc):
return 1;
case array_key_exists('DE',$ac) && !array_key_exists('EN',$bc) && !array_key_exists('EN',$bc):
return 1;
// and so on
}
さらに編集!
実際、複雑な並べ替えの問題についてもっと考えていたので、次の解決策を考え出しました。国のインデックスに表示されるキーワードに基づいて数値ランキングを定義できます。例を含むコードは次のとおりです。
配列の例
$array = array(
array(
'countries' => 'EN,DE,SP',
),
array(
'countries' => 'EN,CH,SP',
),
array(
'countries' => 'DE,SP,CH',
),
array(
'countries' => 'DE,SV,SP',
),
array(
'countries' => 'EN,SP,FR',
),
array(
'countries' => 'DE,FR,CH',
),
array(
'countries' => 'CH,EN,SP',
),
);
ソートルーチン
$rankings = array(
'EN' => 10,
'SP' => 8,
'FR' => 7,
'DE' => 5,
'CH' => 3,
'SV' => 1,
);
usort($array, function (&$a, &$b) use ($rankings) {
if (isset($a['_score'])) {
$aScore = $a['_score'];
}
else {
$aScore = 0;
$aCountries = explode(',',$a['countries']);
foreach ($aCountries as $country) {
if (isset($rankings[$country])) {
$aScore += $rankings[$country];
}
}
$a['_score'] = $aScore;
}
if (isset($b['_score'])) {
$bScore = $b['_score'];
}
else {
$bScore = 0;
$bCountries = explode(',',$b['countries']);
foreach ($bCountries as $country) {
if (isset($rankings[$country])) {
$bScore += $rankings[$country];
}
}
$b['_score'] = $bScore;
}
if ($aScore == $bScore) {
return 0;
}
elseif ($aScore > $bScore) {
return -1;
}
else {
return 1;
}
});
注: このコードは、最高ランクの全体を配列の先頭に並べ替えます。逆の動作が必要な場合は、これを変更します。
elseif ($aScore > $bScore) {
に
elseif ($aScore < $bScore) {
大なり記号が小なり記号に変更されたことに注意してください。この変更を行うと、ランキングが最も低いエントリが配列の先頭にソートされます。これがすべて役立つことを願っています!
また注意してください!
このコードは、各配列に _score 要素を追加するという点で、配列に小さな変更を加えます。この値を保存することで、文字通り2倍以上速度を上げることができたので、これが問題にならないことを願っています(私のベンチマークでは.00038-.00041から.00016-.00018まで)。if
そうでない場合は、キャッシュされた値を取得するブロックを削除しelse
、スコア値を保存する部分を除いて、ブロックの内容を毎回実行します。
ちなみに、var_export()
ソート後の配列のダンプは次のとおりです。
array (
0 => array (
'countries' => 'EN,SP,FR',
'_score' => 25,
),
1 => array (
'countries' => 'EN,DE,SP',
'_score' => 23,
),
2 => array (
'countries' => 'EN,CH,SP',
'_score' => 21,
),
3 => array (
'countries' => 'CH,EN,SP',
'_score' => 21,
),
4 => array (
'countries' => 'DE,SP,CH',
'_score' => 16,
),
5 => array (
'countries' => 'DE,FR,CH',
'_score' => 15,
),
6 => array (
'countries' => 'DE,SV,SP',
'_score' => 14,
),
)
楽しみ!