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
randint -- ohne doppelte Zahlen
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]
@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.
@BlackJack: python <3 ich auch
the more they change the more they stay the same
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.
@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.
Wird random.sample dann nicht selbst eine Liste anlegen?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.
- cofi
- Python-Forum Veteran
- Beiträge: 4432
- Registriert: Sonntag 30. März 2008, 04:16
- Wohnort: RGFybXN0YWR0
Ja, aber eine andere. Man benoetigt ja nur n Elemente und dafuer den Platz von 2n zu belegen ist reichlich unnoetig.
Michael Markert ❖ PEP 8 Übersetzung ❖ Tutorial Übersetzung (3.x) ⇒ Online-Version (Python 3.3) ❖ Deutscher Python-Insider ❖ Projekte
@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:
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)
Danke - docstring lesen hätte hier wirklich geholfen...BlackJack hat geschrieben:Ich zitiere hier mal den Docstring -- bitte besonders auf den letzten Absatz achten:
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]
@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
>>>