【问题标题】:Generating random lists in Python query在 Python 查询中生成随机列表
【发布时间】:2016-06-20 06:36:49
【问题描述】:

我希望我的程序从 1 到 X 取数字,并将这些数字随机分布在 X/2 个列表中 Y 次。我不希望在一次洗牌期间重复一个数字,我也不希望列表重复。因此,如果存在列表 [1,2],则在同一个随机播放中不应该有另一个包含 1 或 2 的列表,并且整个结果中也不应该有另一个 [1,2] 或 [2,1]。

这是我想出的,但是,它不断重复数字。有什么建议吗?

import random

def Shuffler():
    amount = int(raw_input("Numbers up to: "))
    times = int(raw_input("Number of shuffles: "))
    numberslist = range(1,amount+1)
    twos = []
    thisshuffle = []
    final = []

    while len(final) < (amount/2)*times:
      twos = []
      thisshuffle = []
      while len(twos) < 2:
        if len(numberslist)!=0:
          randomnumber = random.choice(numberslist)
          if (randomnumber in twos) or (randomnumber in thisshuffle):
            numberslist.remove(randomnumber)
          else:
            twos.append(randomnumber)
            thisshuffle.append(randomnumber)
            numberslist.remove(randomnumber)
        else:
          numberslist = range(1,amount+1)

      if (twos or list(reversed(twos))) not in final:
        final.append(twos)

    k=0
    for i in range(times): #this shit prints shit
      print "%s:" % (i+1), final[k:k+amount/2]
      print
      k = k + amount/2
    Shuffler()

Shuffler()

【问题讨论】:

    标签: list python-2.7 random shuffle


    【解决方案1】:

    正如 ccf 所指出的,您的要求并非微不足道。再走几步,您就会拥有一个数独生成器 :)
    我尝试了一些解决方案,但它们要么没有产生随机输出,要么效率很低。 Ccf 的解决方案显然写得很好,但似乎也有同样的问题;它产生有序的输出(例如[1, 2], [1, 3], [1, 4], [1, 5], [1, 6])。

    @cff - 使用 itertools.combinations 而不是 itertools.permutations 来避免产生重复不是更好吗?

    这是一个与 ccf 非常相似的“解决方案”(也不产生随机输出):

    import itertools
    
    def Shuffler():
        amount = int(raw_input("Numbers up to: "))
        times = int(raw_input("Number of shuffles: "))
        rng = range(1, amount+1)
        perms = list(itertools.combinations(rng, 2))
        lst_single = []
        lst_all = []
        for p in perms:
            if len(lst_all) >= times:
                for i, lst in enumerate(lst_all):
                    print str(i+1) + ": ", lst
                break
            if len(lst_single) == amount/2:
                lst_all.append(lst_single)
                lst_single = []
            elif p[0] < p[1]:
                p = list(p)
                lst_single.append(p)
    
        Shuffler()
    

    输出

    Numbers up to: 6
    Number of shuffles: 3
    1:  [[1, 2], [1, 3], [1, 4]]
    2:  [[1, 6], [2, 3], [2, 4]]
    3:  [[2, 6], [3, 4], [3, 5]]
    

    这是一个略显老套的解决方案,它似乎可以产生您想要的输出,但效率低下。它依赖于一组来过滤掉不需要的组合,但首先仍然会浪费资源来生产它们。

    import random
    
    def Shuffler():
        amount = int(raw_input("Numbers up to: "))
        times = int(raw_input("Number of shuffles: "))
        rng = range(1, amount+1)
        final = []
        lst_len = amount/2
        combos_unique = set()
        while len(combos_unique) < lst_len*times:
          combo_rand = random.sample(rng, 2)
          if combo_rand[0] < combo_rand[1]:
              combos_unique.add(tuple(combo_rand))
        tmp = []
        for combo in combos_unique:
          tmp.append(list(combo))
          if len(tmp) >= lst_len:
            final.append(tmp)
            tmp = []
        for i, lst in enumerate(final):
          print str(i+1) + ": ", lst
        Shuffler()
    

    输出

    Numbers up to: 6
    Number of shuffles: 3
    1:  [[2, 6], [4, 6], [5, 6]]
    2:  [[4, 5], [1, 3], [1, 6]]
    3:  [[3, 4], [2, 4], [3, 5]]
    

    【讨论】:

      【解决方案2】:

      您不希望在一次随机播放中出现任何重复的数字,以及任何重复的列表......等等。这不是一件容易的事。另外一个事实是,唯一的数字集是固定的,不能设置得太高。例如,如果您设置“最多编号:” 5 和“随机播放次数:” 20,您肯定会得到重复的数字。

      我知道,您的代码的问题在于这个 if 语句:

      if (twos or list(reversed(twos))) not in final:
          final.append(twos)
      

      (twos or list(reversed(twos))) 是逻辑OR,结果是twos,因为twos不为空。我建议您将 if 语句更改为:

      if (twos not in final) and (list(reversed(twos)) not in final):
          final.append(twos)
      

      以下代码 (python 2.7x) 使用排列和随机播放来生成数字列表。接下来,使列表唯一(例如,同一列表中没有 [1,2] 和 [2,1])。然后,根据用户指定的随机播放次数将它们分组。按任意字母,脚本将退出。希望对您有所帮助:

      from itertools import permutations
      from random import shuffle
      
      def Shuffler():
          try:
              amount = input("Numbers up to: ")
              p = list(permutations(range(1, amount + 1), 2))
              p_uniq = [list(x) for x in p if x[::-1] in p and x[0]<=x[1]]
              shuf_max = len(p_uniq) /(amount / 2)
              times = shuf_max + 1   # set a higher value to trigger prompt
      
              while times > shuf_max:
                  shuffle(p_uniq)    # shuffle the unique list in place
                  times = input("Number of shuffles (MAX %s): " % (shuf_max))            
              else:
                  for i, group in enumerate(list(zip(*[iter(p_uniq[: (amount /2) * times + 1])]* (amount/2)))):
                      print "%i: " % (i + 1), list(group)
              Shuffler()
          except:
              print 'quitting...'
      
      Shuffler()
      

      输出:

      Numbers up to: 10
      Number of shuffles (MAX 9): 8
      1:  [[6, 7], [1, 9], [2, 5], [5, 9], [9, 10]]
      2:  [[1, 10], [3, 8], [4, 10], [8, 10], [1, 5]]
      3:  [[1, 4], [6, 8], [3, 6], [2, 4], [4, 7]]
      4:  [[2, 10], [5, 8], [3, 9], [1, 7], [4, 9]]
      5:  [[1, 2], [7, 9], [1, 3], [6, 9], [1, 6]]
      6:  [[2, 9], [4, 8], [3, 5], [8, 9], [7, 10]]
      7:  [[2, 7], [2, 3], [7, 8], [3, 7], [3, 10]]
      8:  [[3, 4], [2, 6], [5, 6], [5, 7], [4, 6]]
      Numbers up to: 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-02-28
        • 2018-10-14
        • 2017-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-21
        相关资源
        最近更新 更多