Сортировка многомерного массива в PHP

В настоящее время я создаю метод сортировки, который состоит из значений из запроса 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"); 

Есть ли кто-нибудь, кто мог бы дать мне намек на то, как с этим справиться?

Related of "Сортировка многомерного массива в PHP"

Лично я использовал бы пользовательскую (анонимную) функцию в сочетании с 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, чтобы узнать, как использовать пользовательскую функцию сравнения.