В настоящее время я создаю метод сортировки, который состоит из значений из запроса mysql.
Вот краткий обзор массива:
Array ( [0] => Array ( ['id'] = 1; ['countries'] = 'EN,CH,SP'; ) [1] => Array ( ['id'] = 2; ['countries'] = 'GE,SP,SV'; ) )
Я преуспел в том, что делаю нормальное использование на основе значений числового идентификатора, но я предпочитаю сортировать массив по содержимому поля «страны» (если в этом случае он содержит заданную строку, код страны), а затем по полю id.
Следующий фрагмент был моей первой идеей, как это сделать, но я понятия не имею, как включить его в рабочую функцию:
in_array('EN', explode(",",$a['countries']) );
Как бы вы это сделали?
Благодаря!
К сожалению, я действительно ничего не понимаю.
Вот что у меня есть на данный момент, и это не дает мне ничего, кроме ошибок: uasort() [function.uasort]: Invalid comparison function
function compare($a, $b) { global $usercountry; if ( in_array($usercountry, $a['countries']) && in_array($usercountry, $a['countries']) ) { $return = 0; } else if (in_array($usercountry, $a['countries'])) { $return = 1; } else { $return = -1; } return $return; } $array= usort($array, "compare");
Есть ли кто-нибудь, кто мог бы дать мне намек на то, как с этим справиться?
Лично я использовал бы пользовательскую (анонимную) функцию в сочетании с usort()
.
EDIT: Re – ваш комментарий. Надеюсь, это положит вас на правильный путь. Эта функция дает равный приоритет элементам, которые имеют EN, либо нет EN, или скорректированному приоритету, когда только один имеет EN.
usort($array,function ($a, $b) { $ac = strpos($a['countries'],'EN'); $bc = strpos($a['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($a['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, ), )
Наслаждайтесь!
Наконец нашел эту замечательную функцию на PHP.net:
function array_msort($array, $cols) { $colarr = array(); foreach ($cols as $col => $order) { $colarr[$col] = array(); foreach ($array as $k => $row) { $colarr[$col]['_'.$k] = strtolower($row[$col]); } } $eval = 'array_multisort('; foreach ($cols as $col => $order) { $eval .= '$colarr[\''.$col.'\'],'.$order.','; } $eval = substr($eval,0,-1).');'; eval($eval); $ret = array(); foreach ($colarr as $col => $arr) { foreach ($arr as $k => $v) { $k = substr($k,1); if (!isset($ret[$k])) $ret[$k] = $array[$k]; $ret[$k][$col] = $array[$k][$col]; } } return $ret; }
Вот как выглядит каждая страна: $ array ['countries'] = in_array ($ needle, $ haystack); }
$array = $array = array_msort($array, array('countries'=>SORT_DESC, 'id'=>SORT_ASC));
Спасибо всем за вашу помощь!
Вы можете рассмотреть array_walk
и array_walk_recursive
и array_map
, которые при объединении возможно могут делать то, что вы хотите сделать.
Попробуйте с array_mulisort .
Проверьте uasort, чтобы узнать, как использовать пользовательскую функцию сравнения.