Возврат случайного элемента из массива Python на основе критериев поиска - PullRequest
2 голосов
/ 22 ноября 2010

Приношу извинения, если это просто, но я искал немного сейчас и не могу найти простое, эффективное решение.

У меня есть двумерный список списков Python, который состоит только изиз 1 и 0.

например:

a=[[0,1,0],[0,1,1],[1,0,1]]

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

[0,1], [1,1], [1,2], [2,0], or [2,2]

с равной вероятностью.

Я мог бы перебрать каждый элемент в структуре и составить список подходящих индексов, а затем выбрать один из них случайным образом, используя random.choice (list)- но это кажется очень медленным, и я не могу не чувствовать, что есть более аккуратный, более питонский способ приблизиться к этому.Я буду делать это, вероятно, для массива 20x20, и мне придется делать это много раз, поэтому я мог бы сделать его максимально эффективным.

Заранее благодарен за любую помощь и совет!

Ответы [ 5 ]

2 голосов
/ 22 ноября 2010

Я бы использовал понимание списка для генерации списка кортежей (позиции 1), затем random.choice:

from random import choice

a = [[0,1,0],[0,1,1],[1,0,1]]
mylist = []

[[mylist.append((i,j)) for j, x in enumerate(v) if x == 1] for i, v in enumerate(a)]
print(choice(mylist))
1 голос
/ 22 ноября 2010

random.choice позволяют нам случайным образом выбирать элемент из списка, поэтому нам просто нужно использовать понимание списка, чтобы создать список индексов, где элементы равны 1, а затем выбрать один вrandom.

Мы можем использовать следующее понимание списка:

>>> a = [[0,1,0],[0,1,1],[1,0,1]]
>>> [(x,y) for x in range(len(a)) for y in range(len(a[x])) if a[x][y] == 1]
[(0, 1), (1, 1), (1, 2), (2, 0), (2, 2)]

Что означает, что мы можем сделать:

>>> import random
>>> random.choice([(x,y) for x in range(len(a)) for y in range(len(a[x])) if a[x][y] == 1])
(1, 1)

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

1 голос
/ 22 ноября 2010

Я бы использовал массив NumPy для достижения этой цели:

from numpy import array
random_index = tuple(random.choice(array(array(a).nonzero()).T))

Если вы храните ваши данные в массивах NumPy с самого начала, этот подход, вероятно, будет быстрее, чем все, что выможно сделать со списком списков.

Если вы хотите выбрать много индексов для одних и тех же данных, есть еще более быстрые подходы.

0 голосов
/ 22 ноября 2010

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

s = set((0, 1), (1, 1), (1, 2), (2, 0), (2, 2))

Чтобы случайным образом выбрать индексную пару, используйте

random.choice(list(s))

Чтобы установить запись в 1, используйте

s.add((i, j))

Чтобы установить запись в 0, используйте

s.remove((i, j))

Чтобы перевернуть запись, используйте

s.symmetric_difference_update([(i, j)])

Чтобы проверить, является ли запись 1, используйте

(i, j) in s
0 голосов
/ 22 ноября 2010

Когда вы получаете свой результат из random.choice, проверьте, соответствует ли он тому, как вы хотите, с правильными элементами, если он снова не является случайным

def return_random(li):
    item = random.choice(li)
    if item == 1: #insert check here
        return item
    else:
        return_random(li)

Редактировать: чтобы избежать путаницы с модулем re, спасибо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...