Лично я бы использовал пользовательскую (анонимную) функцию вместе с usort()
.
РЕДАКТИРОВАТЬ: Re - ваш комментарий. Надеюсь, это поставит вас на правильный путь. Эта функция дает равный приоритет элементам, которые имеют EN или не имеют EN, или настраивают приоритет, когда только один имеет EN.
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 в каждый массив. Надеюсь, это не проблема, так как, сохраняя это значение, я буквально смог увеличить скорость более чем вдвое (.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,
),
)
Наслаждайтесь!