Jo: Zufällig aus array auswählen

Servus zusammen,

Ich hab da zum Jahresende auf ein kleines problem gestoßen zu dem ich einfach keine lösung finde.

Folgendes:

  
$allowed = array(1,2,3,4,5,6,7,8);  
shuffle($allowed);  
$rand_chars = array_rand($allowed, 4);  
foreach($rand_chars AS $char)  
{  
$nr = $allowed[$char];  
echo $nr;  
}  

Soweit alles Klar ich wähle zufällig 4 keys aus dem $allowed Array aus und gebe sie aus.
Aber gibt es eine möglichkeit auch die übergebliebenen Keys auszuwählen (also die die er in $rand_chars nicht auswählt) und auszugeben bzw. mit denen etwas anderes zu machen?

Gruß und Guten Rutsch

Jo

  1. $allowed = array(1,2,3,4,5,6,7,8);

    shuffle($allowed);
    $rand_chars = array_rand($allowed, 4);
    foreach($rand_chars AS $char)

      
    
    > Soweit alles Klar ich wähle zufällig 4 keys aus dem $allowed Array aus und gebe sie aus.  
      
    Nein, du machst da noch mehr: Du schüttelst erstmal dein Losbeutelchen (shuffle), anschließend schüttelst du nochmal dein Losbeutelchen und greifst vier Lose raus (array\_rand).  
      
    Das ist einmal Schütteln zu viel. Der Zufall wird nicht zufälliger, wenn man zweimal auf ihn stößt.  
      
    
    > Aber gibt es eine möglichkeit auch die übergebliebenen Keys auszuwählen  
      
    Werfe das zweite Schütteln raus und benutze einfach die ersten vier Einträge als die eine Gruppe und den Rest als die zweite. Insgesamt in etwa so:  
      
    ~~~php
    $allowed = array(1,2,3,4,5,6,7,8);  
    shuffle($allowed);  
    for ($i = 0; $i < 4; $i += 1) { // mal angenommen, $allowed ist immer größer 4 Einträge  
      echo $allowed[$i];  
    }  
    for ($i = array_size($allowed) - 1; $i >= 4; $i -= 1) {  
      echo $allowed[$i];  
    }
    
    1. Servus;

      Vielen herzlichen dank :) da fällts mir wie schuppen von den augen :)

      Das ist einmal Schütteln zu viel. Der Zufall wird nicht zufälliger, wenn man zweimal auf ihn stößt.

      Ja das dachte ich zu Anfang auch aber ich habe gemerkt bei versuchen mit 100 bis 10000 durchläufen, das array_rand die ersten keys häufiger auswählt als die letzteren und das etwa gleichverteilt, also meinetwegen von 100 versuchen (4 keys ausgewählt also 400 Ergebnisse):
      50% mal 0,
      25% mal 1,
      12.5% mal 3,
      6.25% mal 4,
      3.125% mal 5,
      1.5625% mal 6 und
      0.78...% mal 7.
      (in etwa)
      ka warum das so ist.

      Gruß

      Jo

      1. ich habe gemerkt bei versuchen mit 100 bis 10000 durchläufen, das array_rand die ersten keys häufiger auswählt als die letzteren

        Das liegt möglicherweise daran, dass array_rand() nur zufällige Einträge _nacheinander_ auswählt; die Funktion hüpft also mit zufälligen Sprüngen vorwärts durch die Liste, sie wählt nicht zufällig mal hier einen Eintrag, mal dort.

        Würdest du aus einem Feld mit den Zahlen 1, 2 und 3 drei Einträge auswählen lassen, bekämest du deshalb immer 1, 2, 3 als Ergebnis, niemals eine der im ersten Augenblick vielleicht erwarteten anderen Möglichkeiten. Vom Zufall ist da nichts mehr vorhanden und mein Gefühl – ich bin kein Mathematiker – sagt mir, so viel besser wird es noch nicht, wenn die Auswahlquote von hier 100% auf deine 50% sackt (vier aus acht hattest du im Beispiel).

        Dieser Unsinn ist nur als Anmerkung dokumentiert und konterkariert den gesamten Rest der Beschreibung, "Pick one or more random entries out of an array".

      2. Test:

        <?php
        $ar=array(1,2,3,4,5,6,7,8,9,0);
        $e=array(0,0,0,0,0,0,0,0,0,0);
        for ($i=0; $i<1000000000; $i++) {
            $e[array_rand($ar)]++;
        }
        print_r ($e)
        ?>

        Ergebnis:

        Array
        (
            [0] => 100003559
            [1] => 99989560
            [2] => 99991212
            [3] => 99979222
            [4] => 99968313
            [5] => 99986359
            [6] => 100014004
            [7] => 100051197
            [8] => 100066441
            [9] => 99950133
        )

        Anders ausgedrückt: ich kann das von Dir beschriebene Verhalten nicht nachvollziehen.

        Jörg Reinholz

        1. Noch ein Test:

          <?php  
          $erste=4;  
          $wiederholungen=1000000;  
          $ar=array(1,2,3,4,5,6,7,8,9,0);  
          $e=array(0,0,0,0,0,0,0,0,0,0);  
            
          for( $i=0; $i < $wiederholungen; $i++ ) {  
          	$as=$ar;  
          	shuffle($as);  
          	for ($k=0; $k<$erste; $k++) {  
          	    $z=array_shift($as);  
          	    $e[$z]++;  
          	    #print "$z, ";  
          	}  
          	#print "\n";  
          	# Ab hier ist übrigens nur noch der Rest in $as ...  
          }  
          print_r ($e)  
          ?>
          

          Ergebnis:

          Array
          (
              [0] => 399801
              [1] => 399465
              [2] => 400351
              [3] => 400778
              [4] => 400199
              [5] => 399426
              [6] => 399088
              [7] => 400522
              [8] => 400030
              [9] => 400340
          )

          Ist auch gut verteilt...eine Annäherung an 40% (~ 400000) wäre der nach unendlich vielen Wiederholungen zu erwartende Zustand gewesen.

          Jörg Reinholz

  2. Servus zusammen,

    Soweit alles Klar ich wähle zufällig 4 keys aus dem $allowed Array aus und gebe sie aus.
    Aber gibt es eine möglichkeit auch die übergebliebenen Keys auszuwählen (also die die er in $rand_chars nicht auswählt) und auszugeben bzw. mit denen etwas anderes zu machen?

    Eine sogenannte Ziehung:

    1. Mische die Menge (Array),
    2. ziehe die Elemente (Zahlen) nacheinander aus dieser Menge (shift(), pop()),
    3. nimm den Rest und mach damit was Du willst ;)

    Good luck.

  3. @@Jo:

    nuqneH

    Soweit alles Klar ich wähle zufällig 4 keys aus dem $allowed Array aus und gebe sie aus.
    Aber gibt es eine möglichkeit auch die übergebliebenen Keys auszuwählen (also die die er in $rand_chars nicht auswählt) und auszugeben bzw. mit denen etwas anderes zu machen?

    Sind in $allowed immer 8 Elemente, die du in 4 + 4 aufteilen willst? Wenn die erste Guppe mehr oder gleich viele Elemente wie die zweite enthalten soll, wäre array_chunk() was für dich.

    Ansonsten array_slice().

    Qapla'

    --
    „Talente finden Lösungen, Genies entdecken Probleme.“ (Hans Krailsheimer)