Laden...

Random von Namen (String)

Erstellt von linkbart vor 17 Jahren Letzter Beitrag vor 17 Jahren 16.237 Views
L
linkbart Themenstarter:in
45 Beiträge seit 2006
vor 17 Jahren
Random von Namen (String)

Hallo.

Wie geht das...?

Ich lese aus einer listbox Vornamen aus und möchte diese in einer weiteren Listbox "durchgemischt"(Random) wieder ausgeben!

Mein Eingabe bis jetzt...:

Random r = new Random();
this.listausgabe.Items.Add(r.Next(array.Count));

Aber mit dieser eingabe gibt er mir nur zufallszahlen zurück(zwar in der richtige arraygröße) aber nicht die gemischten Namen..! Was muss ich noch am code ändern??

danke chrisitan

L
497 Beiträge seit 2006
vor 17 Jahren

Du darfst natürlich nicht r.Next zu der Liste hinzufügen, sondern musst diesen Wert als Index verwenden mit dem Du auf die Elemente der original Listbox zugreifst, also quasi originalListbox.Items[zufallszahl]

Sarkusmus ist, wenn nichts mehr hilft, außer Lachen.

L
linkbart Themenstarter:in
45 Beiträge seit 2006
vor 17 Jahren

Hallo

danke für deine antwort aber ganz versteh ich das noch nicht... Ich glaub ich steh auf der leitung oder ich versteh deinen satz nicht ganz.. Also was soll ich denn statt Next hinschreiben...???
Bittte kannst du mir nochmal helfen...

Hier nochmal den ganzen code!


public void OpenFile()
{


System.Windows.Forms.OpenFileDialog OpenFile =  new OpenFileDialog();
						
	OpenFile.Filter = "txt files (*.txt)|*.txt";
	OpenFile.RestoreDirectory = true;
	OpenFile.ShowDialog();		
			

System.IO.Stream os = OpenFile.OpenFile();
System.IO.StreamReader read = new System.IO.StreamReader(os);
		
	while ((line = read.ReadLine()) != null) 
		{
		this.listname.Items.Add(line);
		this.array.Add(line);
		}

					
		}

private void but_ok_Click(object sender, System.EventArgs e)
{
this.OpenFile();
}

private void but_random_Click(object sender, System.EventArgs e)
{
Random r = new Random();
this.listausgabe.Items.Add(r.Next(array.Count));			
}

Danke christian

L
497 Beiträge seit 2006
vor 17 Jahren

Ich meinte das so:


Random r = new Random();
this.listausgabe.Items.Add(r.Next(array.Count));

wird zu


Random r = new Random();
int index = r.Next(array.Count)];
this.listausgabe.Items.Add(originalListbox.Items[index]);

P.S.: Beim Posten von Quell-Code ist es immer hilfreich, die Codetags zu verwenden. Das kannst Du auch nachträglich noch ändern, damit auch Leute, die diesen Thread später lesen sollten, einen schön formatierten und gehighlighteten Code zu sehen bekommen.

Sarkusmus ist, wenn nichts mehr hilft, außer Lachen.

S
1.047 Beiträge seit 2005
vor 17 Jahren

allerdings mußt du noch beachten, das der fall eintreten kann (und sicherlich auch wird), dass 2x der gleiceh name hinzugefügt wird
momentan merkst du dir nämlich nicht, welche namen schon hinzugefügt sind
bzw. du behandelst diese situation nicht

L
linkbart Themenstarter:in
45 Beiträge seit 2006
vor 17 Jahren

Original von sheitman
allerdings mußt du noch beachten, das der fall eintreten kann (und sicherlich auch wird), dass 2x der gleiceh name hinzugefügt wird
momentan merkst du dir nämlich nicht, welche namen schon hinzugefügt sind
bzw. du behandelst diese situation nicht

Hahah danke 😁 Ist mir auch gerade aufgefallen nur leider komm ich schon wieder nicht weiter..

Mein Code:


Random r = new Random();
int index = r.Next(array.Count);
this.listausgabe.Items.Add(this.listname.Items[index]); 
this.listname.Items.RemoveAt(index);

Aber irgendwo ist da ein Fehler. Das RemoveAt funktioniert zwar aber es kommt eine Fehlermeldung: ...auserhalb des gültigen Wertebereichs... ! Irgendwie muss ich das array bzw. den index um eins runtersetzen damit diese fehlermeldung nicht kommt aber wo bzw. wie mach ich das??

Danke christian

L
497 Beiträge seit 2006
vor 17 Jahren

Das liegt daran, dass der Index immer von 0 bin Count - 1 geht. Das hatte ich auch übersehen 🙄

Sarkusmus ist, wenn nichts mehr hilft, außer Lachen.

L
linkbart Themenstarter:in
45 Beiträge seit 2006
vor 17 Jahren

Kein Problem aber wie lös ich das problem bzw. an welcher stelle muss ich index runtersetzten??

danke

L
497 Beiträge seit 2006
vor 17 Jahren

Das hängt davon ab, was Random liefert. Zahlen ab 0 oder ab 1?

Die MDSN sagt Returns a nonnegative random number.

Also nehme ich mal an Werte ab 0?

Dann solltest Du

int index = r.Next(array.Count - 1);

verwenden

Sarkusmus ist, wenn nichts mehr hilft, außer Lachen.

L
linkbart Themenstarter:in
45 Beiträge seit 2006
vor 17 Jahren

Hallo

Das mit

int index = r.Next(array.Count - 1); 

hab ich mir auch schon gedacht kommt aber noch immer die fehlermeldung.. Also mein array hat 12 Werte ( 0-12) also 13 Namen die in meiner Namensliste(orginal nicht durchgemischt) stehen...

danke christian

S
1.047 Beiträge seit 2005
vor 17 Jahren

ich hab mal was gebastelt


private void btnRandomize_Click(object sender, EventArgs e) {
    int size = lstNamen.Items.Count;
    List<String> liste = new List<string>(lstNamen.Items.Count);
    foreach (String s in lstNamen.Items) {
        liste.Add(s);
    }
    Random r = new Random();
    lstRandomized.Items.Clear();
    for (int i = 0; i < size; i++) {
        int index = r.Next(liste.Count);                 
        lstRandomized.Items.Add(liste[index]);
        liste.RemoveAt(index);
    }            
}

ich hab die namen nochmal zwischengespeichert, damit meine ursprüngliche liste nicht verloren geht

durch

r.Next(liste.Count)

begrenze ich den maximalwert des indexes auf die aktuelle länge von liste
das item kommt dann in meine zweite listbox und wird aus der ersten entfernt, wodurch diese um 1 kürzer wird

auf dein problem bezogen müßte dein code so aussehen

Random r = new Random();
for(int i=0;i<array.Count;i++) {
    int index = r.Next(listname.Items.Count);
    listausgabe.Items.Add(listname[index]);
    listname.Items.RemoveAt(index);
}
L
linkbart Themenstarter:in
45 Beiträge seit 2006
vor 17 Jahren

Superrrrrrrrrr Danke es geht!!!!

Schönen Abend noch...

B
1.529 Beiträge seit 2006
vor 17 Jahren

Ich würde aber nicht die Liste kopieren und einzelne Elemente löschen, sondern einfach nur die Elemente mischen:


public void RandomizeList( List<T> TheList )
{
   T swap;
   int swapindex;
   Random ran = new Random( DateTime.Now.GetHashCode() );
   for( int i = 0; i < TheList.Count; i++ )
   {
      swapindex = ran.Next( TheList.Count );
      swap = TheList[ swapindex ];
      TheList[ swapindex ] = TheList[ i ];
      TheList[ i ] = swap;
   }
}

[EDIT von herbivore]In der folgenden Diskussion wird gezeigt, dass dieser Algorithmus keine 100%ig Gleichverteilung produziert. Ein Algorithmus der eine Gleichverteilung liefert findet sich in Zufallszahlen, die sich nicht wiederholen[EDIT]

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo zusammen,

habe nicht alles gelesen, aber vielleicht hilft Zufallszahlen, die sich nicht wiederholen und insbesondere Zufallszahlen, die sich nicht wiederholen .

herbivore

S
1.047 Beiträge seit 2005
vor 17 Jahren

Original von Borg
Ich würde aber nicht die Liste kopieren und einzelne Elemente löschen, sondern einfach nur die Elemente mischen.

danke. sehr schöne und so gesehen elegante lösung. =)

D
11 Beiträge seit 2006
vor 17 Jahren

Original von Borg
Ich würde aber nicht die Liste kopieren und einzelne Elemente löschen, sondern einfach nur die Elemente mischen:

  
public void RandomizeList( List<T> TheList )  
{  
   T swap;  
   int swapindex;  
   Random ran = new Random( DateTime.Now.GetHashCode() );  
   for( int i = 0; i < TheList.Count; i++ )  
   {  
      swapindex = ran.Next( TheList.Count );  
      swap = TheList[ swapindex ];  
      TheList[ swapindex ] = TheList[ i ];  
      TheList[ i ] = swap;  
   }  
}  

> ](http://www.mycsharp.de/wbb2/thread.php?postid=83594#post83594)[EDIT]){orange}

Ich wollte nur mal anmerken, dass dieser Codeschnipsel verdammt nuetzlich ist. Grossen Dank an Borg.

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo Diamantregen,

soweit ich das sehe, hat der Code von Borg aber einen Fehler, nämlich das ran.Next (TheList.Count) statt ran.Next (i + 1) verwendet wird, wodurch die Gleichverteilung nicht sichergestellt ist.

Siehe auch Zufallszahlen, die sich nicht wiederholen

herbivore

B
1.529 Beiträge seit 2006
vor 17 Jahren

Wenn du ran.Next (i + 1) verwendest, wird das Element immer mit einem vor seinem aktuellen Index getauscht, während bei meinem Code mit allen getauscht wird.
Momentan erschließt sich mir nicht, warum durch deine Variante eine bessere Verteilung erreicht werden sollte!?

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo Borg,

[...]Aber nach allem was ich gelesen habe, muss man höllisch aufpassen, damit alle möglichen Ergebnise des Mischens auch wirklich gleich wahrscheinlich sind.

Nach allem was ich weiß, ist bei der folgenden Lösung die Gleichverteilung durch genau al.Count - 1 Vertauschungen sichergestellt:

BTW: Das mit den Count - 1 Vertauschungen kommt noch hinzu. Bei dir wird Count mal vertrauscht.

Der Algorithmus, den ich angegeben habe, habe ich mir nicht ausgedacht, sondern einen gesucht, bei dem die Gleichverteilung erwiesen ist. Und bei meiner damaligen Recherche bin ich eben darauf gestoßen, dass man höllisch aufpassen muss, damit alle möglichen Ergebnise des Mischens auch wirklich gleich wahrscheinlich sind und dass schon kleine Änderungen am Algorithmus die Gleichwahrscheinlichkeit zunichte machen können. Ich kann daher nur raten, den Algorithmus in der von mir angegebenen Form zu verwenden.

herbivore

PS: Den Algorithmus habe ich aus der C++-Standardbibliothek, in deren Dokumentation folgendes zu lesen ist:

This algorithm is described in section 3.4.2 of Knuth (D. E. Knuth, The Art of Computer Programming. Volume 2: Seminumerical Algorithms, second edition. Addison-Wesley, 1981). Knuth credits Moses and Oakford (1963) and Durstenfeld (1964). Note that there are N! ways of arranging a sequence of N elements. Random_shuffle yields uniformly distributed results; that is, the probability of any particular ordering is 1/N!. The reason this comment is important is that there are a number of algorithms that seem at first sight to implement random shuffling of a sequence, but that do not in fact produce a uniform distribution over the N! possible orderings. That is, it's easy to get random shuffle wrong.

B
1.529 Beiträge seit 2006
vor 17 Jahren

Ich wollte dir auch nicht widersprechen. Wie geschrieben, konnte ich es bloß nicht nachvollziehen.
Daher habe ich noch mal im Knuth geblättert. Und festgestellt, dass er auch deine Lösung beschreibt (allerdings wird die Schleifenvariable dekrementiert, das Prinzip bleibt das gleiche).
Ich habe den mathematischen Hintergrund zwar immer noch nicht ganz nachvollziehen können, möchte jedoch eine neue Variante angeben, die sich daran orientiert.
(Siehe Donald E. Knuth, "The Art of Computer Programming", Volume 2, 3rd Edition, Chapter 3.4.2, Page 145, Algorithm P)


public void ShuffleList( List<T> TheList )
{
   T swap;
   int swapindex;
   Random ran = new Random( DateTime.Now.GetHashCode() );
   for( int i = (TheList.Count - 1); i > 0; i-- )
   {
      swapindex = ran.Next( i + 1 );
      swap = TheList[ swapindex ];
      TheList[ swapindex ] = TheList[ i ];
      TheList[ i ] = swap;
   }
}

EDIT:
@herbivore: Du kannst doch nicht einfach diesen Hinweis als PS anhängen, während ich noch danach blättere... Na ja, wenigstens habe ich die dritte Auflage... 😉

D
11 Beiträge seit 2006
vor 17 Jahren

Hallo ihr beiden,

ist ja schon immer wieder verblueffend was eine kleine Aenderung fuer Auswirkungen haben kann. Dummerweise ist es wohl nicht das leichteste dies mathematisch nachzuvollziehen oder sogar selber drauf zu kommen 🤔

Dank an herbivore, dass Du die Diskussion nochmal angeschmissen hast, war sehr hilfreich 🙂

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo Diamantregen,

Dummerweise ist es wohl nicht das leichteste dies mathematisch nachzuvollziehen

naja, gar so schwierig ist es auch nicht. Es gibt n! mögliche Permutationen einer Liste, in der kein Element doppelt vorkommt. Diese Permutationen werden bei dem fraglichen Algorithmus RandomizeList durch eine Folge von n Zufallszahlen erzeugt (bei jedem der n Schleifendurchläufe eine Zufallszahl). Die Anzahl unterschiedlichlicher Zufallsfolgen beträgt nn und jeder der Zufallsfolgen ist gleich wahrscheinlich. Wenn man nun aber mal für den Fall n=3 nn durch n! teilt, also 27/6, bekommt man keine ganze Zahl. Daraus ergibt sich aber, dass die 6 Permutationen nicht alle gleichhäufig erzeugt werden. (Ich habe auch ein Testprogramm geschrieben und in der Tat werden manche Permutationen durch 5 und andere nur durch 4 Zufallsfolgen erzeugt.) Damit ist gezeigt, dass der Algorithmus mit n Durchläufen, der bei jedem Durchlauf Zufallszahlen zwischen 0 und n-1 verwendet, keine Gleichverteilung der möglichen Permutationen erzeugt.

herbivore

B
1.529 Beiträge seit 2006
vor 17 Jahren

Folgendes schreibt Knuth (TAoCP, Vol2, 3rd Ed., p. 145):

R. Salfi has pointed out that Algorithm P cannot possibly generate more than m distinct permutations when we obtain the uniform U's with a linear congruential sequence of modulus m, or indeed whenever we use a recurrence Un+1 = f(Un) for which Un can take only m different values, because the final permutation in such cases is entirely determined by the value of the first U that is generated. Thus, for example, if m = 232, certain permutations of 13 elements will never occur, since 13! =~ 1.45x232.
Remark by Borg: Un is the sequence of random numbers generated

Das bedeutet: Da der Konstruktor von Random bloß ein int als Seed erwartet (und das Vorzeichen ignoriert), kann er auch nur 231 verschiedene Folgen von (Pseudo-)zufallszahlen erzeugen. Desweiteren gibt es auch nur 232 verschiedene Zufallszahlen. Selbst wenn man Double benutzt, bleibt es bei 231 verschiedenenen Folgen mit - da nur die Mantisse verändert wird - nur 252 (siehe IEEE 754) verschiedenen Zufallszahlen und damit gerade mal 1.66 x 17!.
Damit sind - laut obigem Zitat - aber bereits bei 13 bzw. 18 Elementen nicht mehr alle Permutationen möglich.
Somit ist die Gleichverteilung aller Permutationen sowieso nicht gewährleistet.
Herbivore hat zwar nachgewiesen, dass der Algorithmus erst in der jetzigen Form (theoretisch) Gleichverteilung bietet, aber praktisch ist sie nicht mehr zu erreichen.