61

Вопрос по random, list, python – Какой самый питонный способ вывести случайный элемент из списка?

Скажи у меня есть списокx с неизвестной длиной, из которой я хочу случайным образом вытолкнуть один элемент, чтобы впоследствии список не содержал этот элемент. Какой самый питонный способ сделать это?

Я могу сделать это, используя довольно неудобное сочетаниеpop, random.randint, а такжеlen и хотел бы видеть более короткие или более хорошие решения:

import random
x = [1,2,3,4,5,6]
x.pop(random.randint(0,len(x)-1))

Edit: То, чего я пытаюсь добиться, - это последовательно извлекать случайные элементы из списка. (то есть, случайным образом вытолкнуть один элемент и переместить его в словарь, случайным образом вытолкнуть другой элемент и переместить его в другой словарь, ...)


Обратите внимание, что я использую Python 2.6 и не нашел каких-либо решений с помощью функции поиска.

  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от Henrik
  • Error: User Rate Limit ExceededzipError: User Rate Limit ExceededzipError: User Rate Limit Exceeded

    от
  • Error: User Rate Limit ExceededpopError: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceededpypi.python.org/pypi/blistError: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceededfor p in x?

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceededrandom.shuffle(x)Error: User Rate Limit Exceededx.pop()Error: User Rate Limit Exceeded

    от Henrik
  • Error: User Rate Limit ExceededremoveError: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded[for p in x]

    от
  • random.sample(items, items_needed)

    от
  • Я не большая часть Pythonista, но это, конечно, выглядит довольно хорошо для меня.

    от Matt Ball
8 ответов
  • 2

    Не высовываясь из списка

    я столкнулся с этим вопросом в Google, пытаясь получить X случайных элементов из списка без дубликатов. Вот что я в итоге использовал:

    items = [1, 2, 3, 4, 5]
    items_needed = 2
    from random import shuffle
    shuffle(items)
    for item in items[:items_needed]:
        print(item)
    

    Это может быть немного неэффективно, поскольку вы перетасовываете весь список, но используете только небольшую его часть, но я не эксперт по оптимизации, поэтому я могу ошибаться.

  • 2

    Один из способов сделать это: x.remove(random.choice(x))

    Один из способов сделать это:

    x.remove(random.choice(x))
    

  • 38

    Вы не станете намного лучше, чем это, но вот небольшое улучшение:

    x.pop(random.randrange(len(x)))
    

    Документация поrandom.randrange():

    random.randrange([start], stop[, step])
    Return a randomly selected element from range(start, stop, step). This is equivalent to choice(range(start, stop, step)), but doesn’t actually build a range object.

  • 8

    Вот еще одна альтернатива

    почему вы не перетасовываете списокfirst, а затем начать выталкивать элементы, пока не останется больше элементов? как это:

    import random
    
    x = [1,2,3,4,5,6]
    random.shuffle(x)
    
    while x:
        p = x.pop()
        # do your stuff with p
    

  • 8

    Удалитьsingle 

    элемент с произвольным индексом из списка, если порядок остальных элементов списка не имеет значения:

    import r,andom
    
    L = [1,2,3,4,5,6]
    i = random.randrange(len(L)) # get random index
    L[i], L[-1] = L[-1], L[i]    # swap with the last element
    x = L.pop()                  # pop last element O(1)
    

    Обмен используется, чтобы избежать поведения O (n) при удалении из середины списка.

  • 70

    То

    к чему вы, похоже, не привыкли, во-первых, выглядит не очень Pythonic. Вы не должны удалять вещи из середины списка, потому что списки реализованы как массивы во всех реализациях Python, о которых я знаю, так что этоO(n) операция.

    Если вам действительно нужна эта функциональность как часть алгоритма, вы должны проверить структуру данных, такую какblist который поддерживает эффективное удаление из середины.

    В чистом Python, если вы не нуждаетесь в доступе к остальным элементам, вы можете просто перетасовать список, а затем повторить его:

    lst = [1,2,3]
    random.shuffle(lst)
    for x in lst:
      # ...
    

    если тыreally need остаток (который немного пахнет кодом, ИМХО), по крайней мере, вы можетеpop() с конца списка сейчас (что быстро!):

    while lst:
      x = lst.pop()
      # do something with the element      
    

    В общем, вы часто можете выразить свои программы более элегантно, если вы используете более функциональный стиль вместо изменения состояния (как вы делаете со списком).

  • 1

    Этот ответ любезно предоставлен

    @ Никлас-б:

    & Quot;You probably want to use something like pypi.python.org/pypi/blist & Quot;

    ПроцитироватьСтраница PYPI:

    ...a list-like type with better asymptotic performance and similar performance on small lists

    The blist is a drop-in replacement for the Python list that provides better performance when modifying large lists. The blist package also provides sortedlist, sortedset, weaksortedlist, weaksortedset, sorteddict, and btuple types.

    One would assume lowered performance on the random access/random run end, так как это «копия при записи» структура данных. Это нарушает многие предположения прецедентов в списках Python,so use it with care.

    ОДНАКО, если ваш основной вариант использования состоит в том, чтобы сделать что-то странное и неестественное со списком (как в принудительном примере, заданном @OP, или моей проблемой Python 2.6 FIFO с очередью и передачей), то это будет хорошо отвечать всем требованиям. ,

  • 1

    Я знаю, что это старый вопрос, но только для документации:

    Если вы (человек, который гуглит один и тот же вопрос) делаете то, что, как я думаю, вы делаете, то есть случайным образом выбирает k элементов из списка (где k & lt; = len (yourlist)), но при этом убедитесь, что каждый элемент никогда не выбирается более чем один раз (= выборка без замены), вы можете использоватьслучайный пример как @ J-F-Себастьян предлагает. Но, не зная больше о сценарии использования, я не знаю, действительно ли это то, что вам нужно.