Лично я бы использовал пользовательскую (анонимную) функцию в сочетании с 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) {
to
elseif ($aScore < $bScore) {
Обратите внимание, что знак «больше» был заменен символом «меньше». Внесение этого изменения приведет к тому, что элементы с самым низким рейтингом будут отсортированы в начало массива. Надеюсь, все это поможет!
ВНИМАНИЕ ТАКЖЕ!
Этот код внесет небольшое изменение в ваш массив, добавив элемент _score к каждому массиву. Надеюсь, это не проблема, поскольку, сохранив это значение, я буквально смог увеличить скорость более чем вдвое (с 0,00038 до 0,00041 до 0,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,
),
)
Наслаждаться!
person
Dereleased
schedule
13.01.2010
ORDER BY country, id
- person Gordon   schedule 13.01.2010