Frage

Gestern fragte ich diese Frage und nie wirklich eine Antwort bekam, war ich mit wirklich glücklich. Ich möchte wirklich wissen, wie eine Liste von N einzigartigen Zufallszahlen erzeugen eine funktionale Sprache wie Ruby verwenden, ohne extrem unbedingt in der Art sein zu müssen.

Da habe ich nichts sehe ich wirklich mochte, habe ich die Lösung geschrieben ich suchte in LINQ:


       static void Main(string[] args)
        {
            var temp = from q in GetRandomNumbers(100).Distinct().Take(5) select q;
        }

        private static IEnumerable GetRandomNumbers(int max)
        {
            Random r = new Random();
            while (true)
            {
                yield return r.Next(max);
            }
        }

Können Sie meine LINQ Ruby übersetzen? Python? Jede andere funktionale Programmiersprache?

Hinweis: Bitte versuchen Sie es nicht zu viele Schleifen zu verwenden und conditionals - sonst wird die Lösung trivial ist. Auch ich würde lieber eine Lösung sehen, wo Sie kein Array viel größer als N haben zu erzeugen, so können Sie dann nur die Duplikate entfernen und trimmen sich auf N.

Ich weiß, ich bin pingelig, aber ich würde wirklich einige elegante Lösungen für dieses Problem gerne sehen. Dank!

Bearbeiten
Warum alle downvotes?

Ursprünglich mein Codebeispiel hatte das Distinct () nach der Take (), die, wie viele darauf hingewiesen, mich mit einer leeren Liste verlassen konnte. Ich habe die Reihenfolge, in der diese Methoden geändert werden genannt zu reflektieren, was ich in erster Linie gemeint.

Apology:
Ich habe diesen Beitrag gesagt worden, über eher als snobistisch kam. Ich versuche, nicht zu implizieren, dass LINQ ist besser als Rubin / Python; oder dass meine Lösung ist viel besser als alle anderen. Meine Absicht ist, nur um zu erfahren, wie dies zu tun (mit gewissen Einschränkungen) in Ruby. Es tut mir leid, wenn ich als Ruck kam über.

War es hilfreich?

Lösung

In Ruby:

a = (0..100).entries.sort_by {rand}.slice! 0, 5

Aktualisieren : Hier ist eine etwas andere Art und Weise:     a = (0 ... 100) .entries.sort_by {Rand} [0 ... 5]

EDIT:

und In Ruby 1.9 können Sie dies tun:

Array(0..100).sample(5) 

Andere Tipps

>>> import random
>>> print random.sample(xrange(100), 5)
[61, 54, 91, 72, 85]

Dies sollte 5 eindeutige Werte im Bereich 0 — 99 ergeben. Das xrange Objekt erzeugt Werte wie gewünscht, so wird kein Speicher für Werte verwendet, die nicht abgetastet werden.

Hmm ... Wie wäre es (Python):

s = set()
while len(s) <= N: s.update((random.random(),))

Ich werde die einfachstenen Lösungen mit der ‚zufällig‘ Modul verzichten, da ich es nehmen, das ist nicht wirklich das, was Sie nach. Hier ist, was ich glaube, Sie suchen in Python:

>>> import random
>>> 
>>> def getUniqueRandomNumbers(num, highest):
...     seen = set()
...     while len(seen) < num:
...         i = random.randrange(0, highest)
...         if i not in seen:
...             seen.add(i)  
...             yield i
... 
>>>

Um Ihnen zu zeigen, wie es funktioniert:

>>> list(getUniqueRandomNumbers(10, 100))
[81, 57, 98, 47, 93, 31, 29, 24, 97, 10]

Hier ist eine andere Ruby-Lösung:

a = (1..5).collect { rand(100) }
a & a

Ich denke, mit LINQ-Anweisung wird die Distinct Duplikate entfernen, nachdem 5 sind bereits ergriffen worden, so dass Sie nicht mehr als 5 sind garantiert zurück. Jemand kann mich korrigieren, wenn ich falsch liege, aber.

EDIT:. Ok, nur zum Spaß, ein kürzeren und schnelleren (und immer noch mit Iteratoren)

def getRandomNumbers(max, size) :
    pool = set()
    return ((lambda x :  pool.add(x) or x)(random.randrange(max)) for x in xrange(size) if len(a) < size)

print [x for x in gen(100, 5)]
[0, 10, 19, 51, 18]

Ja, ich weiß, sollte Einzeiler gelassen werden Liebhaber Perl, aber ich denke, das ist ein sehr mächtig ist es nicht wahr?

Alte Nachricht hier:

Mein Gott, wie kompliziert ist alles, was! Lassen Sie uns sein pythonic:

import random
def getRandomNumber(max, size, min=0) :
   # using () and xrange = using iterators
   return (random.randrange(min, max) for x in xrange(size))

print set(getRandomNumber(100, 5)) # set() removes duplicates
set([88, 99, 29, 70, 23])

Genießen

EDIT:. Als Kommentatoren bemerkt hat, dies ist eine genaue Übersetzung des Codes der Frage

Um das Problem zu vermeiden, wir haben durch Duplikate nach Erzeugen der Liste zu entfernen, was zu wenig Daten, können Sie eine andere Art und Weise wählen:

def getRandomNumbers(max, size) :
    pool = []
    while len(pool) < size :
        tmp = random.randrange(max)
        if tmp not in pool :
            yield pool.append(tmp) or tmp

print [x for x in getRandomNumbers(5, 5)]
[2, 1, 0, 3, 4]

In Ruby 1.9:

Array(0..100).sample(5)

Python mit Numeric Python:

from numpy import *
a = random.random_integers(0, 100, 5)
b = unique(a)

Voilà! Sicher, dass Sie etwas ähnliches in einem funktionalen Programmierstil tun könnten, aber ... warum?

import random

def makeRand(n):
   rand = random.Random()
   while 1:
      yield rand.randint(0,n)
   yield rand.randint(0,n)      

gen = makeRand(100)      
terms = [ gen.next() for n in range(5) ]

print "raw list"
print terms
print "de-duped list"
print list(set(terms))

# produces output similar to this
#
# raw list
# [22, 11, 35, 55, 1]
# de-duped list
# [35, 11, 1, 22, 55]

Nun, zunächst umschreiben LINQ in Python. Dann ist Ihre Lösung ist ein Einzeiler:)

from random import randrange

def Distinct(items):
    set = {}
    for i in items:
        if not set.has_key(i):
            yield i
            set[i] = 1

def Take(num, items):
    for i in items:
        if num > 0:
            yield i
            num = num - 1
        else:
            break

def ToArray(items):
    return [i for i in items]

def GetRandomNumbers(max):
    while 1:
        yield randrange(max)

print ToArray(Take(5, Distinct(GetRandomNumbers(100))))

Wenn Sie alle einfachen Methoden setzen oben in ein Modul namens LINQ.py, können Sie Ihre Freunde beeindrucken.

(Disclaimer: Natürlich ist dies nicht wirklich LINQ in Python Umschreiben Die Menschen haben die falsche Vorstellung, dass LINQ ist nur ein Haufen von trivialen Erweiterungsmethoden und einige neue Syntax Die wirklich fortgeschrittenen Teil LINQ.. jedoch ist die automatische SQL-Generierung, so dass, wenn Sie eine Datenbank sind Abfragen, es ist die Datenbank ist, die Distinct () und nicht der Client-Seite implementiert.)

Hier ist eine Umschrift von Ihrer Lösung Python.

Zuerst wird ein Generator, der Zufallszahlen erzeugt. Dies ist nicht sehr Pythonic, aber es ist eine gute Übereinstimmung mit dem Beispielcode.

>>> import random
>>> def getRandomNumbers( max ):
...     while True:
...             yield random.randrange(0,max)

Hier ist eine Client-Schleife, die einen Satz von 5 verschiedenen Werten sammelt. Dies ist - wieder -. Nicht die Pythonic Implementierung

>>> distinctSet= set()
>>> for r in getRandomNumbers( 100 ):
...     distinctSet.add( r )
...     if len(distinctSet) == 5: 
...             break
... 
>>> distinctSet
set([81, 66, 28, 53, 46])

Es ist nicht klar, warum Sie einen Generator für Zufallszahlen verwendet werden soll - dass eines der wenigen Dinge, die so einfach ist, dass ein Generator es nicht vereinfachen.

Eine Pythonic Version etwas sein könnte:

distinctSet= set()
while len(distinctSet) != 5:
    distinctSet.add( random.randrange(0,100) )

Sind die Anforderungen 5 Werte generieren und deutlich unter denen, 5, dann so etwas wie

finden
distinctSet= set( [random.randrange(0,100) for i in range(5) ] )

Vielleicht wird Ihre Bedürfnisse anzupassen und ein bisschen mehr linqish aussehen:

from numpy import random,unique

def GetRandomNumbers(total=5):
    while True:
        yield unique(random.random(total*2))[:total]

randomGenerator = GetRandomNumbers()

myRandomNumbers = randomGenerator.next()

Hier ist eine andere Python-Version, genauer die Struktur Ihres C # -Code entspricht. Es gibt keine eingebaute unterschiedliche Ergebnisse zu geben, also habe ich eine Funktion, dies zu tun gegeben.

import itertools, random

def distinct(seq):
    seen=set()
    for item in seq:
        if item not in seen:
            seen.add(item)
            yield item

def getRandomNumbers(max):
    while 1:
        yield random.randint(0,max)

for item in itertools.islice(distinct(getRandomNumbers(100)), 5):
    print item

Ich kann nicht wirklich Ihre LINQ lesen, aber ich denke, Sie versuchen, bis zu 100 5 Zufallszahl zu bekommen und dann Duplikate entfernen.

Hier ist eine Lösung für das:

def random(max)
    (rand * max).to_i
end

# Get 5 random numbers between 0 and 100
a = (1..5).inject([]){|acc,i| acc << random( 100)}
# Remove Duplicates
a = a & a

Aber vielleicht bist du eigentlich auf der Suche für 5 verschiedene Zufallszahl zwischen 0 und 100. In diesem Fall:

def random(max)
    (rand * max).to_i
end

a = []
while( a.size < 5)
    a << random( 100)
    a = a & a
end

Nun, dies könnte man Ihre Sinne von „nicht zu viele Schleifen“, verletzen aber vermutlich nehmen und Distinct verstecken sich nur die von Ihnen Looping. Es wäre leicht genug, nur Methoden in dem aufzählbare die while-Schleife zu verbergen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top