【问题标题】:Python - choosing random object from a listPython - 从列表中选择随机对象
【发布时间】:2012-11-01 00:54:17
【问题描述】:

我有对象列表“p”,每个对象都有一些数字“a”(例如 p[3].a = 5)。我想从列表中选择随机对象,选择对象的概率与其a的值成正比,即选择a=5的对象的概率是选择a=1的对象的概率的五倍.我怎样才能用 Python/Pylab/Numpy 做到这一点?

谢谢!

【问题讨论】:

    标签: python list random python-2.7


    【解决方案1】:

    这适用于整数计数,但对于大计数无效。

    c = collections.Counter({k:k.a for k in stuff})
    random.choice(list(c.elements()))
    

    【讨论】:

    • 没有Counter的等效方法:random.choice([x for x in p for i in range(x.a)])
    【解决方案2】:

    这是一种更有效的方法。

    import random
    
    def weighted_choice(items):
        # check if no items exist
        if not items:
            return None
    
        # compute total of all weights
        total = sum(item.weight for item in items)
    
        # select a random point within the total
        selection = random.randint(0, total - 1)
    
        # find the corresponding item
        count = 0
        for item in items:
            count += item.weight
            if selection < count:
                return item
    

    【讨论】:

      【解决方案3】:

      我建议使用bisect

      from bisect import bisect
      
      class Element(object):
          def __init__(self, value):
              self.a = value
          def __repr__(self):
              return 'Element({})'.format(self.a)
      
      data = [Element(3), Element(5), Element(7), Element(1)]
      last = 0
      breakpoints = []
      for element in data:
          breakpoints.append(last + element.a)
          last += element.a
      print(breakpoints)
      
      for random_value in xrange(last):
          pos = bisect(breakpoints, random_value)
          print(random_value, data[pos])
      

      您只需构建一次带有断点的列表。然后,您可以根据需要将其与相当快速的 bisect 算法一起使用。

      最后一个循环只是为了演示结果。

      编辑:获取断点的另一种方法(我不喜欢 for 循环):

      values = [value.a for value in data]
      breakpoints = [sum(values[:pos+1]) for pos in xrange(len(values))]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-10
        • 2012-02-21
        • 2019-01-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多