Como posso gerar alguns números aleatórios exclusivos entre 1 e 100 usando JavaScript?
javascript
random
integer
numbers
maluco
fonte
fonte
Respostas:
Por exemplo: Para gerar 8 números aleatórios exclusivos e armazená-los em uma matriz, você pode simplesmente fazer isso:
fonte
Returns a random number between 0 (inclusive) and 1 (exclusive)
. Sethe Math.random()
acidentalmente retornar 0, oMath.ceil(0)
também será 0, embora a chance seja baixa.fonte
randlines file | head -10
.Gerar permutação de 100 números e depois escolha em série.
Use o algoritmo Knuth Shuffle (também conhecido como Fisher-Yates shuffle) .
JavaScript:
CÓDIGO COPIADO DO LINK.
EDITAR :
Código aprimorado:
Problema potencial:
Suponha que temos um array de 100 números {por exemplo, [1,2,3 ... 100]} e paramos de trocar após 8 trocas; então, na maioria das vezes, a matriz será semelhante a {1,2,3,76,5,6,7,8, ... os números aqui serão embaralhados ... 10}.
Porque todos os números serão trocados com probabilidade 1/100, então prob. de trocar os primeiros 8 números é 8/100, enquanto prob. de trocar outros 92 é 92/100.
Mas se executarmos o algoritmo para o array completo, teremos certeza de que (quase) todas as entradas são trocadas.
Caso contrário, nos deparamos com uma pergunta: quais 8 números escolher?
fonte
Solução JS moderna usando Set (e caso médio O (n))
fonte
Math.floor(Math.random()*100) + 1
Set
em JS! Porém, essa solução não causaria geração desnecessária de números até que um se encaixasse no requisito de unicidade, especialmente nas últimas iterações, se 8 fosse mais próximo de 100? Assim, acho que prefiro a também elegante respostasort
abaixo.As técnicas acima são boas se você quiser evitar uma biblioteca, mas dependendo se você não tiver problemas com uma biblioteca, eu sugiro que você dê uma olhada no Chance para gerar coisas aleatórias em JavaScript.
Especificamente para resolver sua dúvida, usar o Chance é tão fácil quanto:
Isenção de responsabilidade, como autor de Chance, sou um pouco tendencioso;)
fonte
var codes = chance.unique(chance.string, 8)
Se você precisa dos códigos extraídos de um pool de caracteres específico, pode especificar assim:chance.unique(chance.string, 8, {pool: "abcd1234"})
onde abcd1234 pode ser qualquer caractere que você quiser no pool. Veja chancejs.com/#stringchance.string({ length: 8 })
e se você quiser que apenas alguns caracteres apareçam nessa string,chance.string({ pool: 'abcd1234', length: 8 })
que retornaria uma string aleatória de 8 caracteres dos caracteres abcd1234, por exemplo "2c2c44bc" ou "331141cc"Para evitar embaralhamento longo e não confiável, eu faria o seguinte ...
Voila - sem números repetidos.
Posso postar algum código real mais tarde, se alguém estiver interessado.
Edit: É provavelmente a minha veia competitiva, mas, tendo visto o post de @Alsciende, não pude resistir a postar o código que prometi.
fonte
Outra abordagem é gerar uma matriz de 100 itens com números crescentes e classificá-la aleatoriamente. Na verdade, isso leva a um trecho muito curto e (na minha opinião) simples.
fonte
sort
seja bem implementado, o que tenho certeza que é).Eu faria isso:
fonte
Esta é uma função muito genérica que escrevi para gerar inteiros únicos / não únicos aleatórios para uma matriz. Suponha que o último parâmetro seja verdadeiro neste cenário para esta resposta.
Aqui, o 'tempObj' é um obj muito útil uma vez que cada número aleatório gerado irá verificar diretamente neste tempObj se essa chave já existe, se não, então reduzimos o i em um, pois precisamos de 1 execução extra, uma vez que o número aleatório atual já existe .
No seu caso, execute o seguinte
Isso é tudo.
fonte
min = (min) ? min : 1,
sempre retornará 1. (portanto, 0 nunca será selecionado)Embaralhar os números de 1 a 100 é a estratégia básica correta, mas se você precisar de apenas 8 números embaralhados, não há necessidade de embaralhar todos os 100 números.
Não conheço Javascript muito bem, mas acredito que seja fácil criar um array de 100 nulos rapidamente. Então, por 8 rodadas, você troca o enésimo elemento da matriz (n começando em 0) por um elemento selecionado aleatoriamente de n + 1 a 99. Claro, quaisquer elementos não preenchidos ainda significam que o elemento realmente teria sido o índice original mais 1, então isso é trivial para fatorar. Quando você terminar com as 8 rodadas, os primeiros 8 elementos do seu array terão seus 8 números embaralhados.
fonte
mais curta do que outras respostas que eu vi
fonte
Mesmo algoritmo de permutação que The Machine Charmer, mas com uma implementação prototipada. Mais adequado para um grande número de escolhas. Usa atribuição de desestruturação js 1.7, se disponível.
Edit: Outra proposição, mais adequada para um pequeno número de escolhas, com base na resposta do belugabob. Para garantir a exclusividade, removemos os números escolhidos da matriz.
fonte
para matrizes com buracos como este
[,2,,4,,6,7,,]
porque meu problema era preencher esses buracos. Então eu modifiquei de acordo com minha necessidade :)a seguinte solução modificada funcionou para mim :)
fonte
A melhor resposta inicial é responder por
sje397
. Você obterá os melhores números aleatórios que puder, o mais rápido possível.Minha solução é muito semelhante à solução dele. No entanto, às vezes você quer os números aleatórios em ordem aleatória, e é por isso que decidi postar uma resposta. Além disso, forneço uma função geral.
fonte
Aqui está minha versão do ES6 que construí. Tenho certeza que pode ser um pouco mais consolidado.
fonte
Que tal usar as propriedades do objeto como uma tabela hash ? Dessa forma, seu melhor cenário é randomizar apenas 8 vezes. Só será eficaz se você quiser uma pequena parte do intervalo de números. Também consome muito menos memória do que Fisher-Yates, pois você não precisa alocar espaço para um array.
Então descobri que Object.keys (obj) é um recurso ECMAScript 5, então o acima é praticamente inútil na internet agora. Não tenha medo, porque eu o tornei compatível com o ECMAScript 3 adicionando uma função de teclas como esta.
fonte
fonte
se precisar de mais exclusivo, você deve gerar uma matriz (1..100).
o código acima é mais rápido:
extractUniqueRandomArray (50) => [2, 79, 38, 59, 63, 42, 52, 22, 78, 50, 39, 77, 1, 88, 40, 23, 48, 84, 91, 49, 4, 54, 93, 36, 100, 82, 62, 41, 89, 12, 24, 31, 86, 92, 64, 75, 70, 61, 67, 98, 76, 80, 56, 90, 83, 44, 43, 47, 7, 53]
fonte
Adicionando outra versão melhor do mesmo código (resposta aceita) com a função indexOf do JavaScript 1.6. Não é necessário fazer um loop por todo o array toda vez que você estiver verificando a duplicata.
A versão mais antiga do Javascript ainda pode usar a versão superior
PS: Tentei sugerir uma atualização para o wiki, mas foi rejeitada. Ainda acho que pode ser útil para outros.
fonte
Esta é a minha solução pessoal:
Ele gera aleatoriamente 8 valores de array exclusivos (entre 0 e 7) e os exibe usando uma caixa de alerta.
fonte
Acho que esse método é diferente dos métodos dados na maioria das respostas, então pensei em adicionar uma resposta aqui (embora a pergunta tenha sido feita há 4 anos).
Geramos 100 números aleatórios e marcamos cada um deles com números de 1 a 100. Em seguida, classificamos esses números aleatórios marcados e as marcações são embaralhadas aleatoriamente. Como alternativa, conforme necessário nesta pergunta, pode-se dispensar apenas encontrar os 8 primeiros números aleatórios marcados. Encontrar os 8 itens principais é mais barato do que classificar toda a variedade.
Deve-se notar aqui que o algoritmo de classificação influencia este algoritmo. Se o algoritmo de classificação usado for estável, há uma ligeira tendência a favor de números menores. Idealmente, gostaríamos que o algoritmo de classificação fosse instável e nem mesmo inclinado para a estabilidade (ou instabilidade) para produzir uma resposta com distribuição de probabilidade perfeitamente uniforme.
fonte
Isso pode lidar com a geração de número aleatório UNIQUE de até 20 dígitos
JS
jsFiddle
fonte
Esta solução usa o hash, que tem muito mais desempenho O (1) do que verificar se reside no array. Ele tem verificações de segurança extras também. Espero que ajude.
fonte
Implementar isso como um gerador torna muito bom trabalhar com ele. Observe que essa implementação difere daquelas que exigem que toda a matriz de entrada seja embaralhada primeiro.
Eu escolhi implementar
sample
de uma forma que não modifique o array de entrada, mas você poderia facilmente argumentar que uma implementação mutante é favorável.Por exemplo, a
shuffle
função pode desejar alterar a matriz de entrada original. Ou você pode desejar amostrar da mesma entrada em vários momentos, atualizando a entrada a cada vez.sample
não é mais uma função pura por causa da mutação de entrada do array, mas em certas circunstâncias (demonstradas acima) pode fazer mais sentido.Outra razão pela qual escolhi um gerador em vez de uma função que apenas retorna um array é porque você pode querer continuar a amostragem até alguma condição específica.
Talvez eu queira o primeiro número primo de uma lista de 1.000.000 de números aleatórios.
Como estamos trabalhando com um gerador, essa tarefa é trivial
Isso irá amostrar continuamente 1 número aleatório de cada vez
x
, verificar se é primo e retornarx
se for. Se a lista de números se esgotar antes que um primo seja encontrado,NaN
será retornado.Nota:
Esta resposta foi compartilhada originalmente em outra pergunta que foi fechada como uma duplicata desta. Por ser muito diferente das outras soluções fornecidas aqui, decidi compartilhá-lo aqui também
fonte
fonte
Usar a
Set
é a opção mais rápida. Aqui está uma função genérica para obter um aleatório exclusivo que usa um gerador de callback. Agora é rápido e reutilizável .fonte
Esta é uma implementação do Fisher Yates / Durstenfeld Shuffle , mas sem a criação real de um array, reduzindo assim a complexidade do espaço ou da memória necessária, quando o tamanho da seleção é pequeno em comparação com o número de elementos disponíveis.
Para escolher 8 números de 100, não é necessário criar uma matriz de 100 elementos.
Supondo que uma matriz seja criada,
rnd
) de 1 a 100rnd
Se uma matriz não for criada, um hashMap pode ser usado para lembrar as posições reais trocadas. Quando o segundo número aleatório gerado é igual a um dos números gerados anteriormente, o mapa fornece o valor atual naquela posição ao invés do valor real.
fonte
Aqui está um exemplo de 5 números aleatórios retirados de um intervalo de 0 a 100 (ambos 0 e 100 incluídos) sem duplicação.
fonte
Você também pode fazer isso com um revestimento como este:
[...((add, set) => add(set, add))((set, add) => set.size < 8 ? add(set.add(Math.floor(Math.random()*100) + 1), add) : set, new Set())]
fonte