与给定的单词列表相比,手动排序数组

时间:2013-07-22 23:00:36

标签: php arrays sorting usort

TL; DR:我需要对一系列特定单词进行排序。订单应与现有数组匹配。请参阅最后一个代码块中的示例代码。

我有一系列标题,每个标题的第一个单词是一种颜色。我此时习惯于对数组进行排序,但这一点令人困惑。

问题:我需要根据已排序的单词列表手动对单词数组进行排序。我已设置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' );

4 个答案:

答案 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];
});

答案 1 :(得分: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
)

答案 2 :(得分: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"
}

答案 3 :(得分: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

这应该这样做。