Tentei usar random.randint(0, 100)
, mas alguns números eram iguais. Existe um método / módulo para criar uma lista de números aleatórios exclusivos?
Observação: o código a seguir é baseado em uma resposta e foi adicionado depois que a resposta foi postada. Não faz parte da questão; é a solução.
def getScores():
# open files to read and write
f1 = open("page.txt", "r");
p1 = open("pgRes.txt", "a");
gScores = [];
bScores = [];
yScores = [];
# run 50 tests of 40 random queries to implement "bootstrapping" method
for i in range(50):
# get 40 random queries from the 50
lines = random.sample(f1.readlines(), 40);
Respostas:
Isso retornará uma lista de 10 números selecionados no intervalo de 0 a 99, sem duplicatas.
Com referência ao seu exemplo de código específico, você provavelmente deseja ler todas as linhas do arquivo uma vez e, em seguida, selecionar linhas aleatórias da lista salva na memória. Por exemplo:
Dessa forma, você só precisa realmente ler o arquivo uma vez, antes do loop. É muito mais eficiente fazer isso do que voltar ao início do arquivo e chamar
f1.readlines()
novamente para cada iteração de loop.fonte
Você pode usar a função shuffle do módulo aleatório como este:
Observe aqui que o método shuffle não retorna nenhuma lista como esperado, ele apenas embaralha a lista passada por referência.
fonte
Você pode primeiro criar uma lista de números de
a
ab
, ondea
eb
são, respectivamente, o menor e o maior número em sua lista e, em seguida, embaralhá-la com o algoritmo de Fisher-Yates ou usando orandom.shuffle
método do Python .fonte
A solução apresentada nesta resposta funciona, mas pode se tornar problemática com a memória se o tamanho da amostra for pequeno, mas a população for enorme (por exemplo
random.sample(insanelyLargeNumber, 10)
).Para consertar isso, eu iria com isso:
fonte
random.sample
usa essa abordagem para um pequeno número de amostras de uma grande população, portanto, esse problema com a memória realmente não existe mais. Embora, no momento em que esta resposta foi escrita, a implementação derandom.shuffle
pode ter sido diferente.Gerador de número pseudoaleatório congruencial linear
Este problema pode ser resolvido com um Gerador Congruencial Linear simples . Isso requer sobrecarga de memória constante (8 inteiros) e no máximo 2 * (comprimento de sequência) cálculos.
Todas as outras soluções usam mais memória e mais computação! Se você só precisar de algumas sequências aleatórias, esse método será significativamente mais barato. Para intervalos de tamanho
N
, se você deseja gerar na ordem de sequênciasN
únicask
ou mais, eu recomendo a solução aceita usando os métodos integrados,random.sample(range(N),k)
pois isso foi otimizado em python para velocidade.Código
Uso
O uso desta função "intervalo_aleatório" é o mesmo que para qualquer gerador (como "intervalo"). Um exemplo:
Resultados da amostra
fonte
prime
, a função retornará apenas 4 respostas possíveis, porquevalue
é a única coisa escolhida aleatoriamente com 4 valores possíveis, quando precisamos de pelo menos (4 escolha 2) = 6, (permitindo a ordenação não aleatória).random_range(2,4)
retornará os valores {(1, 0), (3, 2), (2, 1), (0, 3)}, mas nunca o par (3,1) (ou (1,3)). Você está esperando novos números primos grandes gerados aleatoriamente a cada chamada de função?random_range(v)
retorna atév
sequências únicas em vez dev!
)Se a lista de N números de 1 a N for gerada aleatoriamente, então sim, existe a possibilidade de que alguns números possam se repetir.
Se você quiser uma lista de números de 1 a N em uma ordem aleatória, preencha um array com inteiros de 1 a N e, em seguida, use um shuffle de Fisher-Yates ou Python
random.shuffle()
.fonte
Se você precisa amostrar números extremamente grandes, você não pode usar
range
porque joga:
Além disso, se
random.sample
não for possível produzir o número de itens que você deseja devido ao intervalo ser muito pequenolança:
Esta função resolve os dois problemas:
Uso com números extremamente grandes:
Resultado da amostra:
Uso em que o intervalo é menor que o número de itens solicitados:
Resultado da amostra:
Também funciona com intervalos e etapas negativas:
Resultados da amostra:
fonte
Você pode usar a biblioteca Numpy para uma resposta rápida, conforme mostrado abaixo -
O trecho de código dado lista 6 números únicos entre o intervalo de 0 a 5. Você pode ajustar os parâmetros para seu conforto.
Resultado
Ele não impõe nenhuma restrição como vemos em random.sample, conforme referido aqui .
Espero que isso ajude um pouco.
fonte
A resposta fornecida aqui funciona muito bem com relação ao tempo e também à memória, mas um pouco mais complicada, pois usa construções Python avançadas, como rendimento. A resposta mais simples funciona bem na prática, mas o problema dessa resposta é que ela pode gerar muitos inteiros espúrios antes de realmente construir o conjunto necessário. Experimente com PopulaçãoSize = 1000, TamanhoSamostra = 999. Em teoria, existe uma chance de que ele não termine.
A resposta abaixo aborda ambas as questões, pois é determinística e um tanto eficiente, embora atualmente não seja tão eficiente quanto as outras duas.
onde as funções getElem, percolateUp são definidas abaixo
Finalmente, o tempo em média foi de cerca de 15 ms para um grande valor de n como mostrado abaixo
fonte
random.randint
função 3996 vezes, enquanto a outra cca. 6.000 vezes. Não é uma melhoria tão grande, hein?Para obter um programa que gere uma lista de valores aleatórios sem duplicatas que seja determinística, eficiente e construída com construções básicas de programação, considere a função
extractSamples
definida abaixo,A ideia básica é acompanhar os intervalos
intervalLst
de valores possíveis a partir dos quais selecionar nossos elementos necessários. Isso é determinístico no sentido de que temos a garantia de gerar uma amostra dentro de um número fixo de etapas (apenas dependente depopulationSize
esampleSize
).Para usar a função acima para gerar nossa lista necessária,
Também podemos comparar com uma solução anterior (para um valor inferior de populaçãoSize)
Observe que reduzi o
populationSize
valor, pois ele produz Erro de Memória para valores mais altos ao usar arandom.sample
solução (também mencionado nas respostas anteriores aqui e aqui ). Para os valores acima, também podemos observar queextractSamples
supera arandom.sample
abordagem.PS: Embora a abordagem central seja semelhante à minha resposta anterior , há modificações substanciais na implementação, bem como na abordagem, juntamente com a melhoria na clareza.
fonte
Uma função muito simples que também resolve seu problema
fonte
O problema com as abordagens baseadas em conjunto ("se o valor aleatório em valores de retorno, tente novamente") é que seu tempo de execução é indeterminado devido a colisões (que requerem outra iteração "tente novamente"), especialmente quando uma grande quantidade de valores aleatórios é retornada da gama.
Uma alternativa que não está sujeita a esse tempo de execução não determinístico é a seguinte:
fonte
fonte
Se você deseja garantir que os números adicionados são únicos, você pode usar um objeto Set
se estiver usando 2.7 ou superior, ou importe o módulo sets se não.
Como outros mencionaram, isso significa que os números não são verdadeiramente aleatórios.
fonte
para amostrar inteiros sem substituição entre
minval
emaxval
:com jax:
fonte
n_samples
deles? Qual é o seu raciocínio por trás dessa abordagem? Você pode explicar quais são as vantagens de sua abordagem, em comparação com qualquer uma do grande número de respostas existentes (a maioria delas de 8 anos atrás)?random.shuffle
, que usa Mersenne Twister, que é muito mais lento do que algos oferecido por numpy (e provavelmente jax). numpy e jax permitem outros algoritmos de geração de números aleatórios. jax também permite a compilação e diferenciação jit, o que pode ser útil para a diferenciação estocástica. Além disso, em relação a uma matriz "possivelmente grande", algumas das respostas mais votadas fazem exatamente a mesma coisa comrandom.shuffle
, o que eu não acho que seja pecaminoso em um sentido relativo ou mesmo absolutorandom.shuffle
usa Mersenne Twister" - é embaralhamento Fisher-Yates, conforme mencionado em várias respostas. Tem complexidade de tempo linear, portanto, não pode ser assintoticamente mais lento do que algoritmos oferecidos por qualquer outra biblioteca, numpy ou não. Se numpy é mais rápido, é só porque está implementado em C, mas isso não garante a geração de uma permutação enorme (que pode nem caber na memória), apenas para escolher alguns elementos dela. Não há uma única resposta além da sua que faça isso.random
módulo é escrito em Python, então você pode facilmente visualizar seu código-fonte (tenterandom.__file__
).Da CLI no win xp:
No Canadá, temos a Loteria 6/49. Acabei de embrulhar o código acima em lotto.bat e executar
C:\home\lotto.bat
ou apenasC:\home\lotto
.Porque
random.randint
muitas vezes repete um número, eu usoset
comrange(7)
e encurto para 6.Ocasionalmente, se um número se repetir mais de 2 vezes, o comprimento da lista resultante será menor que 6.
EDIT: No entanto,
random.sample(range(6,49),6)
é o caminho correto a seguir.fonte
fonte
print len(result), len(set(result))
. Você esperaria ver queresult
teria elementos exclusivos apenas uma vez a cada1.0851831788708547256608362340568947172111832359638926... × 10^20
tentativa.