2016-08-04 29 views
3

Ich habe eine Reihe von Objekten, die Fußballspieler sind. Das Array kann alles von null bis zu Tausenden von Spielern enthalten. Ich will es zu den besten 10. Mein erster Versuch war zu reduzieren, wie folgt:Reduzieren Sie ein Array von Objekten zu den "besten 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]); 
} 

durch ähnliche Beiträge gelesen, ich bin jetzt bewusst, dass das Problem ist, dass das Array nicht tatsächlich geändert wird, so Die while-Schleife wird für immer fortgesetzt (der Computer sperrt tatsächlich).

So ist mein Versuch, es zu korrigieren, wie folgt, basierend auf den Ratschlägen anderer Beiträge.

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

Wie Sie wahrscheinlich sagen, ich kann nicht verstehen, was an dieser Stelle und verstehe nicht, ich tue, was die $ Schlüsselteil für ist (es von anderen Beispielen nur kopiert wird). Es hängt immer noch nur den PC.

Wie kann ich das korrigieren oder gibt es einen besseren Weg, dies zu erreichen?

Als Antwort auf die Anfrage für die Datenstruktur, hier ist eine Dump von nur 2 Spielern, um zu zeigen, wie sie angeordnet sind.

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

können Sie die Datenstruktur bitte – Kisaragi

+0

Aktualisiert Frage posten, Datenstruktur zeigt. Hoffentlich haben Sie das gewollt? – Farflame

Antwort

2

Mit usort, können Sie zunächst um diesen Wert um das Array sortieren, und dann, array_slice verwenden, nehmen die ersten 10 Elemente:

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

Wow, das ist so viel einfacher und funktionierte zum ersten Mal. Auch sehr schnell. Danke :) – Farflame

2

Ich denke, es kann ein einfacher Ansatz.

Wie wäre es mit dem Ansatz, bei dem wir nach Fertigkeitsstufe sortieren (absteigend), und dann "Slice" die ersten 10, um die besten zu repräsentieren?

Ihre Struktur sieht aus wie so etwas Unter der Annahme:

$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 
... 

Der Code unten würde für Sie tun:

// 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

Danke, du hast absolut recht, das ist ein viel besserer Weg, es zu tun. Verarbeitet sich sehr schnell und funktioniert perfekt. – Farflame

+0

Da die Leute sehr schnell lernten, wann sie Daten auf * Lochkarten (!) Verarbeiten mussten, * ist das Sortieren ein "unerwartet effizienter" Prozess. Viele Vorgänge mit sehr hohen Stückzahlen können sehr effizient ausgeführt werden (selbst wenn Sie nur auf die Verwendung von Lochkarten oder Tape beschränkt sind), wenn Sie möchten, dass alle Datenströme, mit denen Sie arbeiten, identisch sortiert sind . Prozesse, die andernfalls "indizierte Dateien" benötigen (was sie nicht hatten *) * können * sequentiell * ... durchgeführt werden, um "auch immer noch sortierte" Ausgaben zu erzeugen. –

+0

Ich habe einen Prozess neu erstellt, der indexierte Dateien verwendet, um "vorsortierte Streams" in der beschriebenen Weise zu verwenden, und er lief * dreihundert mal schneller * als sein Vorgänger ... * einschließlich * der Sortierzeit! –