Ruby/Python으로 이것을 어떻게 작성합니까? 아니면 내 LINQ를 Ruby/Python으로 번역 할 수 있습니까?

StackOverflow https://stackoverflow.com/questions/122033

문제

어제, 나는 물었다 이것 질문과 내가 정말로 행복했던 답을 얻지 못했습니다. 나는 스타일이 매우 필수적이지 않고 루비와 같은 기능적 언어를 사용하여 N 고유 랜덤 숫자 목록을 생성하는 방법을 알고 싶습니다.

내가 정말 좋아하는 것을 보지 못했기 때문에 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);
            }
        }

내 linq를 루비로 번역 할 수 있습니까? 파이썬? 다른 기능적 프로그래밍 언어가 있습니까?

메모: 너무 많은 루프와 조건부를 사용하지 마십시오. 그렇지 않으면 솔루션은 사소합니다. 또한, N보다 훨씬 큰 배열을 생성 할 필요가없는 솔루션을 볼 수 있으므로 복제물을 제거하고 N으로 줄일 수 있습니다.

나는 내가 까다 롭다는 것을 알고 있지만,이 문제에 대한 우아한 해결책을 정말로보고 싶을 것입니다. 감사!

편집하다:
왜 모든 다운 보트인가?

원래 내 코드 샘플에는 take () 이후에 고유 한 ()가 있었는데, 많은 사람들이 지적했듯이 빈 목록을 남길 수 있습니다. 나는 처음에 내가 의미하는 바를 반영하기 위해 그 방법이 호출되는 순서를 변경했습니다.

사과:
나는이 게시물이 다소 멍청하다고 들었다고 들었습니다. 나는 LINQ가 Ruby/Python보다 낫다는 것을 암시하려고하지 않았다. 또는 내 솔루션이 다른 모든 사람보다 훨씬 낫습니다. 저의 의도는 루비 에서이 작업을 수행하는 방법을 배우는 것입니다. 바보로 만나면 미안 해요.

도움이 되었습니까?

해결책

루비에서 :

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

업데이트: 여기에 약간 다른 방법이 있습니다 : a = (0 ... 100) .entries.sort_by {rand} [0 ... 5

편집하다:

그리고 루비 1.9에서는 다음을 수행 할 수 있습니다.

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

다른 팁

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

이것은 범위에서 5 개의 고유 한 값을 생성해야합니다 0 — 99. 그만큼 xrange 객체는 요청 된대로 값을 생성하므로 샘플링되지 않은 값에는 메모리가 사용되지 않습니다.

흠 ... 어때 (파이썬) :

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

나는 '랜덤'모듈을 사용하여 가장 간단한 솔루션을 포기할 것입니다. 파이썬에서 찾고 있다고 생각하는 것은 다음과 같습니다.

>>> 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
... 
>>>

작동 방식을 보여주기 위해 :

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

또 다른 루비 솔루션은 다음과 같습니다.

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

LINQ 문을 사용하면 5가 이미 촬영 된 후 뚜렷한 사람이 복제를 제거 할 것이므로 5 번을 다시 얻지 못할 것입니다. 그래도 내가 틀렸다면 누군가 나를 교정 할 수 있습니다.

편집 : 좋아, 재미를 위해, 짧고 빠른 것 (그리고 여전히 반복자를 사용하고 있음).

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]

예, 한 라이너가 Perl Lovers에게 맡겨야하지만, 이것이 매우 강력하다고 생각합니까?

여기에 오래된 메시지 :

나의 신, 그 모든 것이 얼마나 복잡한 지! 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])

즐기다

편집 : 주석가가 알 수 있듯이 이것은 질문 코드의 정확한 번역입니다.

목록을 생성 한 후 복제물을 제거하여 얻은 문제를 피하려면 데이터가 너무 적 으면 다른 방법을 선택할 수 있습니다.

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]

루비 1.9에서 :

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

숫자 파이썬이있는 파이썬 :

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

덕! 물론 기능적 프로그래밍 스타일에서 비슷한 일을 할 수는 있지만 ... 왜?

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]

글쎄, 먼저 Python에서 LINQ를 다시 작성합니다. 그러면 솔루션은 1 라이너입니다 :)

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))))

위의 모든 간단한 방법을 Linq.py라는 모듈에 넣으면 친구들에게 깊은 인상을 줄 수 있습니다.

(면책 조항 : 물론 이것은 아닙니다 실제로 Python에서 LINQ를 다시 작성합니다. 사람들은 LINQ가 단지 사소한 확장 방법과 새로운 구문이라는 오해가 있습니다. 그러나 LINQ의 실제로 고급 부분은 자동 SQL 생성이므로 데이터베이스를 쿼리 할 때 클라이언트 측이 아닌 별개의 ()을 구현하는 데이터베이스입니다.)

다음은 솔루션에서 파이썬으로의 음역이 있습니다.

먼저, 랜덤 숫자를 생성하는 생성기. 이것은 그다지 피운은 아니지만 샘플 코드와 잘 일치합니다.

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

다음은 5 개의 별개의 값 세트를 수집하는 클라이언트 루프입니다. 이것은 가장 피스닉 구현이 아닙니다.

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

왜 랜덤 숫자로 발전기를 사용하고 싶은지는 확실하지 않습니다. 이는 생성기가 단순화하지 않기 때문에 간단한 몇 안되는 것 중 하나입니다.

더 피스닉 버전은 다음과 같습니다.

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

요구 사항이 5 개의 값을 생성하고 그 5 가지 중에서 구별되는 경우

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

어쩌면 이것은 당신의 요구에 맞을 것입니다.

from numpy import random,unique

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

randomGenerator = GetRandomNumbers()

myRandomNumbers = randomGenerator.next()

다음은 C# 코드의 구조와 더 밀접하게 일치하는 또 다른 Python 버전입니다. 뚜렷한 결과를 제공하기위한 내장은 없으므로이 작업을 수행하는 기능을 추가했습니다.

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

실제로 LINQ를 읽을 수는 없지만 최대 100 명까지 5 개의 임의 숫자를 얻은 다음 복제물을 제거하려고한다고 생각합니다.

다음은 다음과 같은 해결책입니다.

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

그러나 아마도 당신은 실제로 0과 100 사이에 5 개의 별개의 랜덤 숫자를 찾고있을 것입니다.

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

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

이제 이것은 "너무 많은 루프가 아님"에 대한 당신의 감각을 침해 할 수 있지만, 아마도 당신의 루핑을 숨기고있는 것 같습니다. while 루프를 숨기기 위해 열거 가능한 방법을 추가하는 것은 쉽습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top