2016-08-04 4 views
3

У меня есть массив объектов, которые являются футболистами. Массив может содержать от нуля до тысячи игроков. Я хочу, чтобы уменьшить его до лучших 10. Моя первая попытка была следующей:Уменьшить массив объектов до 'best 10'

while (count($ArrayOfPlayers) > 10) { 

    $ArrayIndex = 0; 
    $WorstPlayerIndex = -1; 
    $WorstPlayerSkill = 9999999999; 
    foreach ($ArrayOfPlayers as $Player) { 
     $Skill = $Player->RatingsArray['Skill']; 
     if ($Skill < $WorstPlayerSkill) { 
      $WorstPlayerIndex = $ArrayIndex; 
      $WorstPlayerSkill = $Skill; 
     } 
     $ArrayIndex += 1; 
    } 

    // Found the worst player in the list, so remove him. 
    unset($ArrayOfPlayers[$WorstPlayerIndex]); 
} 

Начитавшись через подобные посты, я знаю теперь, что проблема заключается в том, что массив фактически не изменяется, так цикл while продолжается вечно (компьютер действительно блокируется).

Так что моя попытка исправить это заключается в следующем, основываясь на советах других сообщений.

while (count($ArrayOfPlayers) > 10) { 

     $WorstIndexPlayer = 0; 
     $WorstPlayerSkill = 9999999999; 
     foreach ($ArrayOfPlayers as $key => &$Player) { 
      $Skill = $Player->RatingsArray['Skill']; 
      if ($Skill < $WorstPlayerSkill) { 
       $WorstIndexPlayer = $key; 
       $WorstPlayerSkill = $Skill; 
      } 
     } 
     // Found the worst player in the list, so remove him. 
     unset($ArrayOfPlayers[$WorstIndexPlayer]); 
} 

Как вы можете сказать, я не понимаю, что я делаю в данный момент и не понимаю, что часть $ ключа для (это просто копируется из других примеров). Он все еще просто висит на ПК.

Как исправить это, или есть лучший способ достичь этого?

В ответ на запрос структуры данных, здесь находится свалка всего 2 игроков, чтобы показать, как они организованы.

Array 
(
[0] => Player Object 
    (
     [ID] => 1 
     [TeamID] => 1 
     [Name] => Joseph Dorrington 
     [RatingsArray] => Array 
      (
       [Skill] => 51993 
      ) 
    ) 

[1] => Player Object 
    (
     [ID] => 2 
     [TeamID] => 1 
     [Name] => Oliver Tillyard 
     [RatingsArray] => Array 
      (
       [Skill] => 64574 
      ) 

    ) 
+0

Вы можете оставить структуру данных, пожалуйста, – Kisaragi

+0

Обновленный вопрос, показывающий структуру данных. Надеюсь, это то, что вы хотели? – Farflame

ответ

2

Используя usort, вы можете сначала отсортировать массив по этому значению, а затем, используя array_slice, взять первые 10 элементов:

function cmp($a, $b){ 
    if ($a->RatingsArray['Skill'] == $b->RatingsArray['Skill']) { 
     return 0; 
    } 
    return ($a->RatingsArray['Skill'] > $b->RatingsArray['Skill']) ? -1 : 1; 
} 
usort($ArrayOfPlayers, "cmp"); 
$ArrayOfPlayers = array_slice($ArrayOfPlayers, 0, 10); 
+1

Ничего себе, это намного проще и сработало в первый раз. Также очень быстро. Спасибо :) – Farflame

2

Я думаю, что может быть более простой подход.

Как насчет подхода, в котором мы сортируем по уровню навыка (по убыванию), а затем «срезаем» первые 10, чтобы представить лучшее?

Если предположить, что структура выглядит примерно так:

$arrayOfPlayers = array (size=6) 
0 => 
    object(stdClass)[1] 
     public 'RatingsArray' => 
     array (size=1) 
      'Skill' => int 1187 
    1 => 
    object(stdClass)[2] 
     public 'RatingsArray' => 
     array (size=1) 
      'Skill' => int 44 
    2 => 
    object(stdClass)[3] 
     public 'RatingsArray' => 
     array (size=1) 
      'Skill' => int 494 
    3 => 
    object(stdClass)[4] 
     public 'RatingsArray' => 
     array (size=1) 
      'Skill' => int 584 
    4 => 
    object(stdClass)[5] 
     public 'RatingsArray' => 
     array (size=1) 
      'Skill' => int 730 
    5 => 
    object(stdClass)[6] 
     public 'RatingsArray' => 
     array (size=1) 
      'Skill' => int 613 
... 

Ниже код будет делать это для вас:

// Call our custom usort function 
usort($arrayOfPlayers, 'sort_players'); 
// Slice the array to the best 10. Note array_slice doesn't care if there's less than 10 
$best = array_slice($arrayOfPlayers, 0, 10); 

// Our custom sorting function 
function sort_players($a, $b) { 
    if ($a->RatingsArray['Skill'] == $b->RatingsArray['Skill']) { 
     return 0; 
    } 

    return ($a->RatingsArray['Skill'] < $b->RatingsArray['Skill']) ? 1: -1; 
} 
+0

Спасибо, ты совершенно прав, это гораздо лучший способ сделать это. Процессы очень быстро и прекрасно работают. – Farflame

+0

Поскольку люди очень быстро узнали, когда им приходилось обрабатывать данные на перфокартах (!), * Сортировка - это «неожиданно эффективный» процесс. Многие операции очень большого объема могут быть выполнены очень эффективно (даже если вы ограничены перфокартами или лентой, как когда-то были люди), если вам требуется, чтобы все потоки данных, с которыми вы работаете, отсортированы одинаково , Процессы, которые в противном случае могли бы потребовать «индексированные файлы» (которые у них не были * есть ...) * могут быть выполнены * последовательно * ... созданием «также все еще отсортированных» выходов. –

+0

Я перестроил процесс, который использовал индексированные файлы для использования «предварительно отсортированных потоков» в описанном порядке, и он работал * в три сотни раз быстрее *, чем его предшественник ... * включая * время сортировки! –