Ruby/Python으로 이것을 어떻게 작성합니까? 아니면 내 LINQ를 Ruby/Python으로 번역 할 수 있습니까?
-
02-07-2019 - |
문제
어제, 나는 물었다 이것 질문과 내가 정말로 행복했던 답을 얻지 못했습니다. 나는 스타일이 매우 필수적이지 않고 루비와 같은 기능적 언어를 사용하여 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 루프를 숨기기 위해 열거 가능한 방법을 추가하는 것은 쉽습니다.