Seite 1 von 1

randint -- ohne doppelte Zahlen

Verfasst: Samstag 12. Juni 2010, 19:52
von acidk
Hallo Pythongemeinde!

Ich möchte mir ca. 100 Zufallszahlen (ganzzahlig) aus einem Zahlenraum von 1- 1000 ausgeben lassen --- ohne dass eine Zahl doppelt ist.
randint() bringt leider doppelte Einträge mit.

Kennt jemand von Euch eine bereits implementierte Methode des Ziehens ohne Zurücklegens?
Ansonsten : selbst eine Liste erzeugen, Zufallszahl ziehen und die Ausgangsliste sukzessiv verkleinern!?

Danke & Gruß,

flo

Re: randint -- ohne doppelte Zahlen

Verfasst: Samstag 12. Juni 2010, 20:22
von str1442

Code: Alles auswählen

>>> random.sample(range(1, 1001), 100)
[753, 336, 341, 636, 101, 231, 484, 97, 372, 414, 200, 653, 218, 116, 831, 109, 862, 454, 118, 722, 772, 100, 937, 902, 39, 502, 954, 611, 228, 233, 906, 864, 509, 729, 975, 574, 282, 979, 761, 205, 359, 494, 338, 635, 571, 84, 148, 935, 213, 889, 885, 374, 78, 921, 681, 515, 464, 63, 493, 508, 992, 489, 543, 824, 783, 853, 964, 619, 430, 329, 872, 899, 626, 435, 850, 555, 562, 999, 117, 346, 602, 91, 918, 119, 731, 893, 914, 355, 300, 776, 276, 704, 690, 437, 683, 353, 867, 66, 616, 762]

Re: randint -- ohne doppelte Zahlen

Verfasst: Samstag 12. Juni 2010, 20:28
von BlackJack
@str1442: Unter Python <3 vielleicht besser `xrange()`, dann muss keine Liste angelegt werden. Bei 1000 Elementen geht das ja noch, aber es skaliert halt nicht gut. :-)

Re: randint -- ohne doppelte Zahlen

Verfasst: Samstag 12. Juni 2010, 20:37
von Dav1d
@BlackJack: python <3 ich auch :twisted:

Re: randint -- ohne doppelte Zahlen

Verfasst: Samstag 12. Juni 2010, 20:42
von str1442
Das hatte ich zuerst auch so, wollte den Quelltext aber Python 3 idiomatisch halten, obwohl ich momentan nur 2.5 & 2.6 benutze - ich nahm an, inzwischen sei das ziemlicher Standard, damit niemand von den unterschiedlichen Versionen verwirrt wird / man nicht ewig auf die Versionsgeschichte eingehen muss? Ausnahme, wenn derjenige selbst Python < 3 benutzt oder man es explizit erwähnt.

Re: randint -- ohne doppelte Zahlen

Verfasst: Samstag 12. Juni 2010, 20:56
von BlackJack
@str1442: Also ich gehe immer davon aus, dass es sich um Python 2.x dreht solange nichts anderes gesagt wird oder es aus dem Quelltext wirklich deutlich ersichtlich ist. Python 3.x empfinde ich halt als unbrauchbar für den produktiven Einsatz. Es fehlen (für mich zumindest) wichtige Bibliotheken und 3 ist AFAIK noch bei keiner Linuxdistribution die Standardversion.

Re: randint -- ohne doppelte Zahlen

Verfasst: Samstag 12. Juni 2010, 22:15
von bords0
BlackJack hat geschrieben:@str1442: Unter Python <3 vielleicht besser `xrange()`, dann muss keine Liste angelegt werden. Bei 1000 Elementen geht das ja noch, aber es skaliert halt nicht gut. :-)
Wird random.sample dann nicht selbst eine Liste anlegen?

Re: randint -- ohne doppelte Zahlen

Verfasst: Samstag 12. Juni 2010, 22:36
von cofi
Ja, aber eine andere. Man benoetigt ja nur n Elemente und dafuer den Platz von 2n zu belegen ist reichlich unnoetig.

Re: randint -- ohne doppelte Zahlen

Verfasst: Sonntag 13. Juni 2010, 00:03
von BlackJack
@bords0: `random.sample()` wird keine zusätzliche Liste mit *allen* Zahlen anlegen. Wozu auch?

Ich zitiere hier mal den Docstring -- bitte besonders auf den letzten Absatz achten:

Code: Alles auswählen

n [1389]: random.sample?
Type:           instancemethod
Base Class:     <type 'instancemethod'>
String Form:    <bound method Random.sample of <random.Random object at 0x81eb794>>
Namespace:      Interactive
File:           /home/bj/random.py
Definition:     random.sample(self, population, k)
Docstring:
    Chooses k unique random elements from a population sequence.

    Returns a new list containing elements from the population while
    leaving the original population unchanged.  The resulting list is
    in selection order so that all sub-slices will also be valid random
    samples.  This allows raffle winners (the sample) to be partitioned
    into grand prize and second place winners (the subslices).

    Members of the population need not be hashable or unique.  If the
    population contains repeats, then each occurrence is a possible
    selection in the sample.

    To choose a sample in a range of integers, use xrange as an argument.
    This is especially fast and space efficient for sampling from a
    large population:   sample(xrange(10000000), 60)

Re: randint -- ohne doppelte Zahlen

Verfasst: Sonntag 13. Juni 2010, 09:37
von snafu
Ja, bei *extrem großen* Wertebereichen spielt `xrange()` tatsächlich seine Stärke aus. Das zeigt sich auch sehr deutlich, wenn man an das Beispiel aus der Doku noch eine Null dranhängt.

Re: randint -- ohne doppelte Zahlen

Verfasst: Sonntag 13. Juni 2010, 10:58
von bords0
BlackJack hat geschrieben:Ich zitiere hier mal den Docstring -- bitte besonders auf den letzten Absatz achten:
Danke - docstring lesen hätte hier wirklich geholfen...
Ich hatte - naiv - erwartet, dass sample mit beliebigen (endlichen) iterables funktioniert. Verlangt werden aber sequences (__len__ und __getitem__ (ohne slices) reichen aus).

Code: Alles auswählen

import random
class R(object):
    def __init__(self, n):
        self.n = n
    def __len__(self):
       return self.n
    def __getitem__(self, i):
       return i
       
print random.sample(R(10000000), 60)

Code: Alles auswählen

[5280304, 2146322, 6204070, 4886913, 2718223, 4380233, 4221235, 6118917, 9844575, 9696442, 9128220, 8143202, 8026412, 5773508, 3330574, 6575526, 6544951, 6845380, 5935171, 4709120, 9104670, 3812544, 1222064, 5548997, 9788092, 5804768, 8285612, 5397606, 2096968, 5282663, 9971843, 2917535, 3298974, 5330993, 9804053, 7262250, 5434644, 6456028, 9664188, 6054484, 9446025, 2895681, 1142644, 4629462, 6666284, 8197343, 2127831, 1868123, 1604313, 2584585, 6243585, 7276640, 832201, 5698673, 9787499, 4696277, 3647415, 5245245, 2465056, 9532502]
Bei beliebigen iterables müsste man erst mal eine Liste erstellen, da man ja nicht mal weiß, wie groß die Population ist. Bei xrange hat man die Länge und kann auf einzelne Elemente zugreifen - das reicht aus, auch wenn man keine "echte" sequence hat.

Re: randint -- ohne doppelte Zahlen

Verfasst: Sonntag 13. Juni 2010, 11:57
von HerrHagen
@acidk: Bei solchen Dingen auch immer recht nützlich: random.shuffle.

Code: Alles auswählen

>>> import random
>>> l = range(10)
>>> l
0: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> random.shuffle(l)
>>> l
1: [9, 7, 5, 2, 1, 8, 3, 0, 6, 4]
>>> l.pop()  # Ziehen
2: 4
>>> 

Re: randint -- ohne doppelte Zahlen

Verfasst: Montag 14. Juni 2010, 18:52
von acidk
:D Vielen, vielen Dank!!