2016-10-23 12 views
0

でレーサー/選手を並べ替え:私は、次の形式で提示いくつかのレーサーに関するデータを持っている場所

 
    array(
     array(name => "the first racer", places => [1,3,1,5,6,2,6,7,8]), 
     array(name => "the second racer", places => [2,4,2,5,7]) 
     ... 
    ) 

は、最初のレーサーがより良い場所を持っている人だったようにそれらを並べ替えるための最良の方法を助言します。たとえば、最初のレーサーが少なくとも1つの第1の場所を持ち、もう1つのレーサーがない場合、最初のレーサーはリストの上位です。彼らの両方が最初の場所を持っている場合は、最初の場所の数を比較してください。数字が等しい場合は、2番目の場所などを比較してください。

私のソリューション(これは非常にエレガントに見えないかもしれない、それは何らかの形で容易に行うことができます。):

 

    $racers = array(
     array('name' => "the first racer", 'places' => [1,3,1,5,6,2,6,7,8,9]), 
     array('name' => "the second racer", 'places' => [1,3,1,5,6,2,6,7,8]), 
     array('name' => "the third racer", 'places' => [2,3,2,5,7,10]), 
     array('name' => "the fourth racer", 'places' => [2,3,10,6,6,10]), 
     array('name' => "the fifth", 'places' => [2,3,2,5,7,10,1]), 
    ); 

    usort($racers, function($prev, $next) { 
     // order places for every racer 
     sort($prev['places']); 
     sort($next['places']); 

     //compare each place with each other 
     foreach ($prev['places'] AS $key => $prevRacerPlace) { 
      // if all values are equal, we compare the number of races 
      if (!isset($next['places'][$key])) { 
       return -1; 
      } 
      $nextRacerPlace = $next['places'][$key]; 
      $diff = $prevRacerPlace - $nextRacerPlace; 
      if ($diff !== 0) { 
       return $diff; 
      } 
     } 
     // if all values are equal, we compare the number of races 
     if (count($next['places']) > count($prev['places'])) { 
      return 1; 
     } 
    }); 

    var_dump($racers); 

+6

.. – Darren

+0

@Darrenをソートすることにより、各レーサーのためにあったか多くの場所を定義し、私はしようとしましたが、私のバージョンは好きではありません。非常に面倒です。私は説明に加えました。 – GrayRF

+0

[** this for .. **](https://www.tehplayground.com/AaivOksiMojdpjAf) – Darren

答えて

3

カスタムの並べ替えの前にいくつかの準備を行うにはかなりいいだろう。だから我々は、ラムダ関数でネストされた並べ替えを避ける:

foreach ($racers as $index => $racer) { 
    $racers[$index]['sorted_places'] = $racer['places']; 
    sort($racers[$index]['sorted_places']); 
} 

ラムダ関数をソートするには、我々は準備ソート場所の頭を比較し、最初に定義された値を返します。 よりレーサーB首位結果、より良い場合は、レーサー首位結果をBよりも良い場合は1を返し、-1を返します。等しい結果では、次のトップの場所のチェックを続行します。

usort($racers, function ($a, $b) { 
    unset($value); 
    do { 
     $topA = array_shift($a['sorted_places']); 
     $topB = array_shift($b['sorted_places']); 

     if (is_null($topA) && is_null($topB)) { 
      $value = 0; 
     } elseif (is_null($topA)) { 
      $value = 1; 
     } elseif (is_null($topB)) { 
      $value = -1; 
     } elseif ($topA > $topB) { 
      $value = 1; 
     } elseif ($topA < $topB) { 
      $value = -1; 
     } 
    } while (!isset($value)); 
    return $value; 
}); 
1

もう1つのアルゴリズムはありますが、私はMax Zuberのソリューションがより効率的だと思います。とにかく:

array_count_values

foreach ($racers as &$racer) { 
    $racer['number_places'] = array_count_values($racer['places']); 
} 

あなたは、少なくとも自分でこの問題を解決しようとしている必要があり
usort($racers, function($current, $next) { 

    $next_places = $next['number_places']; 
    $current_places = $current['number_places']; 

    for ($i=1; $i<=max($next_places, $current_places); $i++) { 

     if (!isset($current_places[$i]) && !isset($next_places[$i])) { 
      continue; 
     } 

     if (!isset($current_places[$i])) { 
      return 1; 
     } 

     if (!isset($current_places[$i]) 
      || $current_places[$i] > $next_places[$i]) 
     { 
      return -1; 
     } 
    } 
}); 
関連する問題