2013-07-22 4 views
0

TL; Мне нужно отсортировать массив конкретных слов. Порядок должен соответствовать существующему массиву. См. Пример кода в последнем блоке кода.Ручная сортировка массива по сравнению с заданным списком слов

У меня есть массив названий, первое слово каждого названия - цвет. Я привык к сортировке массивов на данный момент, но это сбивает с толку.

Проблема: Мне нужно вручную отсортировать массив слов на основе списка слов, которые уже отсортированы. Я uasort настроен так, что у меня есть следующие две переменные, готовые для сравнения:

// first comparison: 
$a_first = strtolower($a_split[0]); // white 
$b_first = strtolower($b_split[0]); // blue 

// 2nd comparison: 
$a_first = strtolower($a_split[0]); // purple 
$b_first = strtolower($b_split[0]); // white 

// 3rd comparison: 
$a_first = strtolower($a_split[0]); // blue 
$b_first = strtolower($b_split[0]); // purple 

Мне нужно сортировать эти цвета от пояса ранжировании, для системы ранжирования джиу-джитсу. Вот массив в правильном порядке:

$color_order = explode(' ', 'white blue purple brown black black-red coral white-red red'); 

/* $color_order = 
Array (
    [0] => white 
    [1] => blue 
    [2] => purple 
    [3] => brown 
    [4] => black 
    [5] => black-red 
    [6] => coral 
    [7] => white-red 
    [8] => red 
) 

Current (incorrect) results: 
1. Blue 
2. Purple 
3. White 

Desired results: 
1. White 
2. Blue 
3. Purple 
*/ 

Мой текущий код, который выходит из uasort(), сортировка по алфавиту с STRCMP. Мне нужно заменить strcmp тем, что может сортировать с помощью моего цветового массива. (Fyi, цвета не соответствуют слову, они перемещаются в другой массив, поэтому здесь не требуется проверка ошибок).

// Sort Step 1: Sort belt level by color 
// $video_categories[belt_id][term]->name = "White belt example" 

function _sort_belt_names($a, $b) { 
    $a_name = trim($a['term']->name); 
    $b_name = trim($b['term']->name); 

    $a_split = explode(' ', $a_name); 
    $b_split = explode(' ', $b_name); 

    if ($a_split && $b_split) { 
    $color_order = explode(' ', 'white blue purple brown black black-red coral white-red red'); 

// IMPORTANT STUFF BELOW! ---- 
    $a_first = strtolower($a_split[0]); // purple 
    $b_first = strtolower($b_split[0]); // white 

    // Compare $a_first $b_first against $color_order 
    // White should come first, red should come last 
    // Return -1 (early), 0 (equal), or 1 (later) 
// IMPORTANT STUFF ABOVE! ---- 
    } 

    // If explode fails, sort original names alphabetically. 
    return strcmp($a_name, $b_name); 
} 

// --- 

uasort($video_categories, '_sort_belt_names'); 
+0

Что такое 'belt_id' в' $ video_categories [belt_id] '? Разве это не идентификатор цвета? Таким образом, вы можете сортировать по этому поводу. – bitWorking

+0

Нет, это часть более крупной системы. Идентификатор пояса из базы данных и является довольно произвольным. Эта система предназначена для сортировки, если бы было уже что-то упорядоченное правильно, тогда это не было бы проблемой;) –

ответ

1

Не видя пример массива, это своего рода трудно кода, но что-то, как это должно работать:

usort($arr, function ($a, $b){ 
    $ord =array_flip(array ('white', 'blue', 'purple', 'brown', 'black', 'black-red', 'coral', 'white-red', 'red')); 
    return $ord[$b] - $ord[$a]; 
}); 
+0

Да, сложно просто «вырезать кусок» для вас, ребята, на SO. Я подумал, что это будет довольно просто, как только вы сломаете его. И я думаю, это было правильно. Array flip отлично работает! Я знал, что ответ будет в ключах массива для цветов, но я не мог на него наложить. Спасибо –

+0

Добро пожаловать. –

1

Вот пользовательская функция сравнения, которая использует список предварительно определенного порядка.

function cmp($a,$b) { 
    $order = array_flip(
     array(
     'white', 
     'blue', 
     'purple', 
     'brown', 
     'black', 
     'black-red', 
     'coral', 
     'white-red', 
     'red', 
    ) 
    ); 
    $a = strtolower($a); 
    $b = strtolower($b); 
    if(!isset($order[$a])) { 
     if(!isset($order[$b])) { 
     return strcmp($a,$b); 
     } 
     return 1; 
    } 
    if(!isset($order[$b])) { 
     return -1; 
    } 
    return $order[$a] - $order[$b]; 
} 

Любое 2 слова, которые есть в списке, соответствуют их порядку. Если в списке 1 слово, а другое - нет, последнее слово «нижнее». Если оба они не существуют в списке, они сопоставляются с любыми другими парами строк.

Используйте функцию с usort, как это:

$colors = array(
    'blue', 
    'purple', 
    'white', 
    'foo', 
    'bar', 
); 
usort($colors,'cmp'); 
print_r($colors); 

Вы получите:

Array 
(
    [0] => white 
    [1] => blue 
    [2] => purple 
    [3] => bar 
    [4] => foo 
) 
1
<?php 
function _sort_belt_names($a, $b) { 

    $a_split = explode(' ', $a); 
    $b_split = explode(' ', $b); 

    if ($a_split && $b_split) { 
    $color_order = explode(' ', 'white blue purple brown black black-red coral white-red red'); 

// IMPORTANT STUFF BELOW! ---- 
    // Convert all the elements in $a_split and $b_split to lowercase 

    foreach ($color_order as $key => $value) { 
     if (in_array($value , $a_split) || in_array($value, $b_split)) { 
      $sorted[] = $value; 
     } 

    } 
    var_dump($sorted); 
// IMPORTANT STUFF ABOVE! ---- 
    } 

    // If explode fails, sort original names alphabetically. 
    // Do whatever you whant to do if explode fails 
} 

$a = "black white coral blue"; 
$b = "black-red purple"; 
_sort_belt_names($a, $b); 
?> 

$ php sorting.php 
array(6) { 
    [0]=> 
    string(5) "white" 
    [1]=> 
    string(4) "blue" 
    [2]=> 
    string(6) "purple" 
    [3]=> 
    string(5) "black" 
    [4]=> 
    string(9) "black-red" 
    [5]=> 
    string(5) "coral" 
} 
1

Не уверен, что uasort является правильным выбором для этого. Как насчет проверки вашего входного массива от массива цветов (перевернутого) и порядок их путем добавления их в массив шпонки на перевернутое значении (ранее числовой ключ):

// Sort Step 1: setup color sort array(s) 
$color_order = explode(' ', strtolower('white blue purple brown black black-red coral white-red red')); 
$color_keyed = array_flip($color_order); 

// Sort Step 2: Sort belt level by color 
// $video_categories[belt_id][term]->name = "White belt example" 

$unmatched=array(); 
$categorised=array(); 
$catsorted=array(); 
foreach($video_categories as $a) { 

    $a_names = explode(' ',strtolower(trim($a['term']->name))); 
    $a_name=$a_names[0]; 
    // check if $a_name is a value in $color_order or a key in $color_keyed 
    if (!array_key_exists("$a_name",$color_keyed) { 
    $unmatched[]=$a; 
    } else { 
    // separated these 2 commands to make more readable but could have done: 
    // $categorised[$color_keyed["$a_name"]][]=$a; 
    // Putting the video_categories item into an array ordered by the key value of the matching color. 
    $catkey=$color_keyed["$a_name"]; 
    $categorised[$catkey][]=$a; 
    } 
} 

// You can now run a double foreach over the 2 dimensional $categorised array 
// to pick out the ordered video_categories entries: 
// then write them to a single dimensional array 
foreach ($categorised as $colkey=>$catkeyed) 
{ 
    foreach ($catkeyed as $cat) { 
    $catsorted[]=$cat; 
} 
// --- 
// $catsorted should now be a flat array 
// containing the original $video_categories array entries 
// sorted by the order of the grade colors above 

Это должно сделать это.

Смежные вопросы