【问题标题】:python: how to know the index when you randomly select an element from a sequence with random.choice(seq)python:当您使用 random.choice(seq) 从序列中随机选择一个元素时如何知道索引
【发布时间】:2011-09-01 22:06:20
【问题描述】:

我非常了解如何从带有random.choice(seq) 的列表中选择一个随机项目,但我如何知道该元素的索引?

【问题讨论】:

  • 另一种可能是随机选择索引,然后按索引访问序列。

标签: python random indexing choice


【解决方案1】:
import random
l = ['a','b','c','d','e']
i = random.choice(range(len(l)))
print i, l[i]

【讨论】:

  • 这样一个优雅的答案。
  • 对 random.choices(range(len(l)), k=n) 也有效,其中 n 是您想要的随机抽奖次数。
【解决方案2】:

您可以先选择一个随机索引,然后让该位置的列表元素同时具有索引和值。

>>> import random
>>> a = [1, 2, 3, 4, 5]
>>> index = random.randint(0,len(a)-1)
>>> index
0
>>> a[index]
1

【讨论】:

    【解决方案3】:

    您可以使用 random 模块中的 randrange 函数

    import random
    l = ['a','b','c','d','e']
    i = random.randrange(len(l))
    print i, l[i]
    

    【讨论】:

      【解决方案4】:

      如果这些值在序列中是唯一的,您总是可以说:list.index(value)

      【讨论】:

      • 不幸的是,如果您在数组中的每个元素上使用它,它将是O(N^2),并且如果任何值重复,则会给出非常倾斜/不正确的结果。
      • “如果任何值重复...”,我的回答是“如果值是唯一的”。我很欣赏您的评论,但请具体说明 my 的答案,而不是仅仅复制/粘贴您的评论以获得其他人的答案。
      【解决方案5】:

      这样做最优雅的方式是random.randrange

      index = random.randrange(len(MY_LIST))
      value = MY_LIST[index]
      

      也可以在 python3 中使用 random.choicerange 对象上执行此操作,但不那么优雅(但仍然比 .index 更好):

      index = random.choice(range(len(MY_LIST)))
      value = MY_LIST[index]
      

      唯一有效的解决方案是这个解决方案和random.randint 解决方案。

      使用list.index 的不仅速度很慢(每次查找时使用O(N) 而不是O(1);如果你对每个元素都这样做会变得非常糟糕,你将不得不进行O(N^2) 比较)而且还如果列表元素不是唯一的,您将得到倾斜/不正确的结果。

      有人会认为这很慢,但事实证明它只比其他正确的解决方案random.randint 稍慢,并且可能更具可读性。我个人认为它更优雅,因为不必像randint(0,len(...)-1) 那样做数字索引摆弄和使用不必要的参数,但有些人可能认为这是一项功能,尽管需要知道randint 的约定包含范围 [start, stop]

      random.choice 的速度证明: 唯一可行的原因是 range 对象已针对索引进行了优化。作为证明,你可以做random.choice(range(10**12));如果它遍历整个列表,你的机器会慢得像爬行。

      编辑:我忽略了 randrange,因为文档似乎说“不要使用这个函数”(但实际上是指“这个函数是 pythonic,使用它”)。感谢 martineau 指出这一点。

      你当然可以把它抽象成一个函数:

      def randomElement(sequence):
          index = random.randrange(len(sequence))
          return index,sequence[index]
      
      i,value = randomElement(range(10**15))  # try THAT with .index, heh
                                              # (don't, your machine will die)
                                              # use xrange if using python2
      # i,value = (268840440712786, 268840440712786)
      

      【讨论】:

      • 这究竟比randint“更优雅”是什么?
      • @martineau:“并且可能更具可读性”-当然,我会澄清一下[编辑]
      • 嗯,看起来randrange(len(MY_LIST)) 可能会更优雅(不需要-1 或单独的range())——虽然不知道速度(因为我没有Py3 已安装)但 2.7 文档说它实际上并没有构建范围对象。
      • @martineau:谢谢,这很奇怪。我之前看过那个函数,文档模棱两可,暗示它“不是你在 Python 中想要的”,所以我认为它是一个低级函数(就像模块公开的其他东西一样)。显然,他们的意思是“这比那更 Pythonic”,或者其他一些奇怪的语法结构。它绝对不会构建范围对象。
      • +1 表示randrange 版本。我将文档解释为它比 choice(range(start, stop, step)) 更好 因为 它实际上并没有构建 range 对象。在 3.2 文档中有一条注释,randint(a, b) 只是 randrange(a, b+1) 的别名,这似乎也暗示了对它的偏好。
      【解决方案6】:

      按照建议使用 randrage() 是获取索引的好方法。通过创建通过comprehension 创建的字典,您可以将此代码减少到一行,如下所示。请注意,由于该字典只有一个元素,因此当您调用 popitem() 时,您会得到一个元组中的组合索引和值。

      import random
      
      letters = "abcdefghijklmnopqrstuvwxyz"
      
      # dictionary created via comprehension
      idx, val = {i: letters[i] for i in [random.randrange(len(letters))]}.popitem()
      
      print("index {} value {}" .format(idx, val))
      

      【讨论】:

        【解决方案7】:

        我们也可以使用 sample() 方法。 如果你想从列表中随机选择 n 个元素

        import random
        l, n = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 2
        index_list = random.sample(range(len(l)), n)
        

        index_list 将具有唯一索引。

        我更喜欢sample() 而不是choices(),因为sample() 不允许序列中有重复元素。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2023-01-04
          • 1970-01-01
          • 2019-08-13
          • 2023-03-30
          • 2014-07-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多