代码之家  ›  专栏  ›  技术社区  ›  Esteban Araya

如何用ruby/python编写这个?或者,你能把我的linq翻译成ruby/python吗?

  •  8
  • Esteban Araya  · 技术社区  · 16 年前

    昨天,我问 this 我从来没有得到一个真正满意的答案。我真的很想知道如何使用Ruby之类的函数语言生成一个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翻译成Ruby吗?蟒蛇?还有其他的函数式编程语言吗?

    注: 请尽量不要使用太多的循环和条件,否则解决方案很简单。另外,我更愿意看到一个解决方案,您不必生成比n大得多的数组,这样您就可以删除重复项并将其修剪为n。

    我知道我很挑剔,但我真的想看看这个问题的一些优雅的解决方案。 谢谢!

    编辑:
    为什么所有的否决票?

    最初,我的代码示例在take()之后有distinct(),正如许多人指出的那样,它可能会给我留下一个空列表。我已经改变了这些方法的调用顺序,从一开始就反映了我的意思。

    道歉:
    有人告诉我这篇文章有点势利。我并不是想暗示linq比ruby/python好,或者我的解决方案比其他人都好。我的目的只是学习如何在ruby中(有一定的约束)做到这一点。如果我被人认为是个混蛋,我很抱歉。

    14 回复  |  直到 14 年前
        1
  •  5
  •   horseyguy    14 年前

    露比:

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

    更新 :这里有一个稍微不同的方法: A=(0…100)。条目。按rand[0…5]排序

    编辑:

    在Ruby1.9中,您可以这样做:

    Array(0..100).sample(5) 
    
        2
  •  13
  •   Jeremy Meo    16 年前
    >>> import random
    >>> print random.sample(xrange(100), 5)
    [61, 54, 91, 72, 85]
    

    这将在范围内产生5个唯一值 0 — 99 . 这个 xrange 对象根据请求生成值,因此没有内存用于未采样的值。

        3
  •  3
  •   Will Boyce    16 年前

    隐马尔可夫模型。。。(python)怎么样?

    s = set()
    while len(s) <= N: s.update((random.random(),))
    
        4
  •  2
  •   Thomas Wouters    16 年前

    我将放弃使用“随机”模块的最简单的解决方案,因为我认为这不是你真正想要的。以下是我认为您在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
    ... 
    >>>
    

    要向您展示它是如何工作的:

    >>> list(getUniqueRandomNumbers(10, 100))
    [81, 57, 98, 47, 93, 31, 29, 24, 97, 10]
    
        5
  •  2
  •   David Mohundro alexsmn    16 年前

    下面是另一个Ruby解决方案:

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

    我认为,有了您的LINQ语句,distinct将在5个已被占用之后删除重复项,因此您不保证返回5个。如果我错了,有人可以纠正我。

        6
  •  2
  •   Bite code    16 年前

    编辑:好的,只是为了好玩,一个更短更快的(仍然使用迭代器)。

    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爱好者,但我认为这个程序非常强大,不是吗?

    此处显示旧消息:

    天哪,这一切有多复杂!让我们做蟒蛇吧:

    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]
    
        7
  •  1
  •   horseyguy    14 年前

    红宝石1.9:

    Array(0..100).sample(5)
    
        8
  •  0
  •   Dan Lenski    16 年前

    带数字python的python:

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

    Voice!当然,您也可以用函数式编程的方式做类似的事情,但是……为什么?

        9
  •  0
  •   Joe Skora    16 年前
    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]
    
        10
  •  0
  •   apenwarr    16 年前

    首先用python重写linq。那么你的解决方案是一条直线:)

    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,因此当查询数据库时,实现distinct()的是数据库,而不是客户端。)

        11
  •  0
  •   S.Lott    16 年前

    下面是从您的解决方案到python的音译。

    首先,生成随机数的生成器。这不是很像蟒蛇,但它与您的示例代码很匹配。

    >>> 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) ] )
    
        12
  •  0
  •   user19087    16 年前

    也许这能满足你的需求,看起来更像是Linqish:

    from numpy import random,unique
    
    def GetRandomNumbers(total=5):
        while True:
            yield unique(random.random(total*2))[:total]
    
    randomGenerator = GetRandomNumbers()
    
    myRandomNumbers = randomGenerator.next()
    
        13
  •  0
  •   Brian    16 年前

    这是另一个Python版本,更接近于C代码的结构。没有一个内置函数可以给出不同的结果,所以我添加了一个函数来实现这一点。

    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
    
        14
  •  -1
  •   hjdivad    16 年前

    我真的看不懂你的LINQ,但我认为你是想得到5个随机数,最多100个,然后删除重复数。

    这是一个解决方案:

    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
    

    但也许你实际上在寻找5个介于0和100之间的不同随机数。在这种情况下:

    def random(max)
        (rand * max).to_i
    end
    
    a = []
    while( a.size < 5)
        a << random( 100)
        a = a & a
    end
    

    现在,这个可能违背了你的“不太多循环”的感觉,但是假设take和distinct只是对你隐藏循环。只需将方法添加到Enumerable以隐藏while循环就足够容易了。