1에서 100 사이의 고유 한 난수 생성


99

JavaScript를 사용하여 1에서 100 사이의 고유 한 난수를 생성하려면 어떻게 해야합니까?


19
이것은 자바 스크립트에 초점을 맞추고 있기 때문에 실제로 속지 않습니다.
dotty

2
@dotty 잘 자바 스크립트로하는 것과 다른 언어로하는 것 사이에 본질적인 차이는 없지만 나는 투표를 종료하지 않을 것입니다.
Pointy

1
나도 종결 투표하지 않을 것입니다. 이것은 충분히 구체적입니다.
Josh Stodola


1
이 작업을 수행하는 또 다른 깨끗한 방법이 있습니다. stackoverflow.com/questions/51898200/…
Huangism

답변:


174

예 : 8 개의 고유 한 난수를 생성하여 배열에 저장하려면 다음과 같이하면됩니다.

var arr = [];
while(arr.length < 8){
    var r = Math.floor(Math.random() * 100) + 1;
    if(arr.indexOf(r) === -1) arr.push(r);
}
console.log(arr);


15
실제 코드는 의사보다 같은 질문에 대한 훨씬 더 그렇다) (의사 ...)이었다 내 대답은 삭제
로마 Starkov

3
O를 선택할 수 있습니다. var randomnumber = Math.ceil (Math.random () * 100) 사용
Alsciende

9
-1 :이 알고리즘은 순진한 접근 방식입니다. 매우 비효율적입니다.
Frerich Raabe

40
와. 순진한 것 같습니다. 최상의 솔루션은 아닐 수 있지만 간단하고 짧으며 진행 상황을 쉽게 파악할 수 있으며 수행해야하는 작업에 대해 허용 가능한 작동 매개 변수 내에서 실행됩니다. 다음 작업으로 넘어갑니다. 완벽은 훌륭하지만 '완료'가 '완벽'보다 낫습니다.
adam0101 2010 년

4
함수가 배열에서 0을 반환 할 가능성이 있습니다. 이 링크에 따르면 : developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… , Math.random () Returns a random number between 0 (inclusive) and 1 (exclusive). 경우 the Math.random()실수로 0을 반환는이 Math.ceil(0)기회가 부족하지만, 또한 0입니다.
Qian Chen

43
  1. 1부터 100까지의 숫자로 배열을 채 웁니다.
  2. 셔플합니다 .
  3. 결과 배열의 처음 8 개 요소를 가져옵니다.

8
확실히 처음 8 번의 셔플 만 수행하도록 코드를 조정하는 것이 더 효율적입니까? (그런 다음 semi-shuffled 배열의 마지막 8 개 요소를 가져옵니다)
두 번째

1
이것이 내가 항상하는 방법이기도하다. 따라서 여러 줄이있는 파일에서 임의의 줄 10 개를 원하면 randlines file | head -10.
tchrist

1
이 확률 허용 대답하지 않는 distrubtion, 유지 때문에, 적절한 대답은 생각
의 Tomás 로베르토

2
N = 10 ^ 12이면 어떨까요? 별로 효율적이지 않습니다.
shinzou

2
현실 세계에서 @shinzou는 JavaScript를 사용하여 10 ^ 12 숫자를 정렬하지 않습니다. tirival 질문에는 사소한 대답이 필요합니다. 나는 세계 기아를 해결하기 위해 여기있는 것이 아닙니다. 나는 그것을 할 준비가 잘되어 있지만 그것이 질문의 대상이 아닙니다.
ЯegDwight

14

100 개의 숫자 순열 을 생성 한 다음 순차적으로 선택합니다.

사용 크 누스 셔플 (일명 피셔 - 예이츠 셔플) 알고리즘 .

자바 스크립트 :

  function fisherYates ( myArray,stop_count ) {
  var i = myArray.length;
  if ( i == 0 ) return false;
  int c = 0;
  while ( --i ) {
     var j = Math.floor( Math.random() * ( i + 1 ) );
     var tempi = myArray[i];
     var tempj = myArray[j];
     myArray[i] = tempj;
     myArray[j] = tempi;

     // Edited thanks to Frerich Raabe
     c++;
     if(c == stop_count)return;

   }
}

링크에서 복사 된 코드.

수정 :

개선 된 코드 :

function fisherYates(myArray,nb_picks)
{
    for (i = myArray.length-1; i > 1  ; i--)
    {
        var r = Math.floor(Math.random()*i);
        var t = myArray[i];
        myArray[i] = myArray[r];
        myArray[r] = t;
    }

    return myArray.slice(0,nb_picks);
}

잠재적 인 문제점:

100 개의 숫자 배열이 있고 {예 : [1,2,3 ... 100]} 8 번의 스왑 후 스와핑을 중지한다고 가정합니다. 그러면 대부분의 경우 배열은 {1,2,3,76,5,6,7,8, ... 숫자가 섞여서 ... 10}처럼 보일 것입니다.

모든 숫자는 1/100 확률로 교환되므로 확률이 높습니다. 처음 8 개 숫자를 교체하는 횟수는 8/100이지만 prob입니다. 다른 92 개의 스와핑은 92/100입니다.

그러나 전체 배열에 대해 알고리즘을 실행하면 (거의) 모든 항목이 스왑된다는 것을 확신합니다.

그렇지 않으면 우리는 어떤 8 개의 숫자를 선택해야할까요?


5
이 방법은 정확하지만 차선책입니다. 8 개의 난수 만 필요하므로 8 번의 스왑 후에 셔플 링을 중지 할 수 있습니다. 위의 코드는 전체 배열을 교체합니다 (이 시나리오에서는 100 개의 요소).
Frerich Raabe

코드가 크게 개선 될 수 있습니다. 반환 값, 부작용 및 함수 사용은 모두 정말 모호한 IMO입니다. fisherYates 함수를 사용하여 원래 문제에 정확히 답하는 함수를 작성하면 더 명확해질 것입니다.
Alsciende 2010 년

1
개선 된 코드로 업데이트 된 답변. 또한 @Frerich Raabe : 8 번의 스왑 후 중단 문제가 언급되었습니다.
Pratik Deoghare 2010 년

Fisher-Yates 알고리즘이 잘못되었습니다. r은 i에 의존해야합니다. 내 anwser를 참조하십시오 stackoverflow.com/questions/2380019/...
Alsciende

죄송합니다. 내 끔찍한 실수! 당신의 구현은 멋지다. 좋아요. +1. 다른 문제가 있으면 알려주세요. 감사합니다.
Pratik Deoghare 2010 년

12

Set (및 평균 케이스 O (n))을 사용한 최신 JS 솔루션

const nums = new Set();
while(nums.size !== 8) {
  nums.add(Math.floor(Math.random() * 100) + 1);
}

console.log([...nums]);


왜 O (n)입니까? 임의의 시간 동안 반복 할 수 없습니까?
Anthony Wieser

@AnthonyWieser 당신이 맞아요, 최악의 경우. Set.add가 o (1)이기 때문에 평균 케이스를 암시했습니다
Alister

그것은 사용으로 변경되기 전에 나는이에 사용되는 내 대답처럼 0을 반환 할 수 있다고 생각Math.floor(Math.random()*100) + 1
adam0101

SetJS 에서 발견하는 것은 매우 멋지다 ! 그러나이 솔루션은 고유성 요구 사항에 맞을 때까지, 특히 마지막 반복에서 8이 100에 가까울 때까지 불필요한 숫자 생성을 유발하지 않을까요? 따라서 나는 sort아래의 우아한 대답을 선호한다고 생각 합니다.
Gilad Barner

10

위의 기술은 라이브러리를 피하고 싶다면 좋지만, 라이브러리를 사용해도 괜찮을지 여부에 따라 JavaScript에서 임의의 항목을 생성 하는 기회 를 확인하는 것이 좋습니다 .

특히 질문을 해결하기 위해 Chance를 사용하면 다음과 같이 쉽습니다.

// One line!
var uniques = chance.unique(chance.natural, 8, {min: 1, max: 100});

// Print it out to the document for this snippet so we can see it in action
document.write(JSON.stringify(uniques));
<script src="http://chancejs.com/chance.min.js"></script>

면책 조항, Chance의 저자로서 나는 약간 편견이 있습니다.)


내가 전에 실행 코드 스 니펫을 본 적이 없기 때문에 Upvote
surfmuggle

고유해야하는 쿠폰 코드 (8 개의 임의의 영숫자 문자열)를 만들고 싶다면 Chance.js로 어떻게 할 수 있습니까? 참고 : 쿠폰은 주문형으로 만들어 지므로 코드 수는 한정되지 않습니다
Oscar Yuandinata

@OscarYuandinata는 간단 var codes = chance.unique(chance.string, 8)합니다. 특정 문자 풀에서 가져온 코드가 필요한 경우 다음과 같이 지정할 chance.unique(chance.string, 8, {pool: "abcd1234"})수 있습니다 . 여기서 abcd1234는 풀에서 원하는 모든 문자가 될 수 있습니다. chancejs.com/#string
Victor Quinn

@VictorQuinn, 미안합니다. 쿠폰 코드는 8 개의 임의의 영숫자 문자열의 배열이 아니라 8 자의 임의의 영숫자 문자열입니다. 하하하 ..
오스카 Yuandinata

Oh @OscarYuandinata 그게 훨씬 더 쉬우 며 chance.string({ length: 8 })특정 문자 만 해당 문자열에 나타나게 chance.string({ pool: 'abcd1234', length: 8 })하려면 abcd1234 문자에서 임의의 8 자 문자열을 반환합니다 (예 : "2c2c44bc"또는 "331141cc")
Victor Quinn

8

길고 신뢰할 수없는 셔플을 피하기 위해 다음을 수행합니다.

  1. 순서대로 1에서 100 사이의 숫자를 포함하는 배열을 생성합니다.
  2. 1에서 100 사이의 난수 생성
  3. 배열의이 인덱스에서 숫자를 찾아 결과에 저장하십시오.
  4. 어레이에서 elemnt를 제거하여 더 짧게 만듭니다.
  5. 2 단계부터 반복하되 99를 난수의 상한으로 사용합니다.
  6. 2 단계부터 반복하되 난수의 상한으로 98을 사용합니다.
  7. 2 단계부터 반복하되 난수의 상한으로 97을 사용합니다.
  8. 2 단계부터 반복하되 난수의 상한으로 96을 사용합니다.
  9. 2 단계부터 반복하되 95를 난수의 상한으로 사용합니다.
  10. 2 단계부터 반복하되 난수의 상한으로 94를 사용합니다.
  11. 2 단계부터 반복하되 난수의 상한으로 93을 사용합니다.

Voila-반복되는 숫자가 없습니다.

누군가 관심이 있다면 나중에 실제 코드를 게시 할 수 있습니다.

편집 : 그것은 아마도 나에게 경쟁적인 연속이지만 @Alsciende의 게시물을 보았을 때 약속 한 코드를 게시하는 것을 거부 할 수 없었습니다.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<title>8 unique random number between 1 and 100</title>
<script type="text/javascript" language="Javascript">
    function pick(n, min, max){
        var values = [], i = max;
        while(i >= min) values.push(i--);
        var results = [];
        var maxIndex = max;
        for(i=1; i <= n; i++){
            maxIndex--;
            var index = Math.floor(maxIndex * Math.random());
            results.push(values[index]);
            values[index] = values[maxIndex];
        }
        return results;
    }
    function go(){
        var running = true;
        do{
            if(!confirm(pick(8, 1, 100).sort(function(a,b){return a - b;}))){
                running = false;
            }
        }while(running)
    }
</script>
</head>

<body>
    <h1>8 unique random number between 1 and 100</h1>
    <p><button onclick="go()">Click me</button> to start generating numbers.</p>
    <p>When the numbers appear, click OK to generate another set, or Cancel to stop.</p>
</body>


하지만 8 번째 숫자는 1부터 100까지가 아니라 1부터 92까지 무작위입니다. 90 개의 숫자를 선택해야한다면 마지막 숫자는 1부터 10까지만 선택됩니다. 그렇지 않나요?
adam0101 2010 년

@ adam0101 아니요, 그는 번호를 선택할 때 번호를 제거하기 때문입니다. 따라서 5 단계에서는 배열에 99 개의 숫자 만 있습니다. @belugabob 당신은 Knuth Shuffle보다 효율적이지 않습니다. 사실, 스플 라이스는 (완벽하게 신뢰할 수있는) 셔플보다 아마 더 비싼
Alsciende

@ adam0101 : 그는 배열에서 선택한 요소를 제거하고 있습니다 (위의 4 단계 참조). 따라서 요소가 두 번 선택되는 것을 방지합니다. 그런 다음 배열이 더 짧기 때문에 다음 난수에 대해 하한을 사용합니다.
Frerich Raabe

@Alsciende, 예-셔플을 사용하여이 작업을보다 효율적으로 수행 할 수있는 방법이있을 것이라고 생각했지만 완전히 확신하지는 못했습니다. 배열에서 항목을 삭제하지 않으려면 배열의 마지막 항목 (선택한 항목이 아닌 경우)을 선택한 위치에 복사하면됩니다.
belugabob 2010 년

1
values.length를 줄이지 않는 이유는 메모리를 재 할당하여 배열 길이를 줄이는 것이 수행되지 않는다는 보장이 없기 때문입니다. maxIndex를 사용하면 배열의 마지막 항목이 관련이 없게되므로 무시하는 것과 동일한 효과가 있습니다.
belugabob 2010 년

8

또 다른 방법은 오름차순 숫자가있는 100 개 항목 배열을 생성하고 무작위로 정렬하는 것입니다. 이것은 실제로 매우 짧고 (내 의견으로는) 간단한 스 니펫으로 이어집니다.

const numbers = Array(100).fill().map((_, index) => index + 1);
numbers.sort(() => Math.random() - 0.5);
console.log(numbers.slice(0, 8));


이것이 제가 가장 좋아하는 대답입니다. 왜 6 표만 얻었는지. 우아하고 복잡합니다 ( sort잘 구현되어 있다고 확신합니다).
Gilad Barner

3

나는 이것을 할 것이다 :

function randomInt(min, max) {
    return Math.round(min + Math.random()*(max-min));
}
var index = {}, numbers = [];
for (var i=0; i<8; ++i) {
    var number;
    do {
        number = randomInt(1, 100);
    } while (index.hasOwnProperty("_"+number));
    index["_"+number] = true;
    numbers.push(number);
}
delete index;

3

이것은 배열에 대해 임의의 고유하거나 고유하지 않은 정수를 생성하기 위해 작성한 매우 일반적인 함수입니다. 이 답변에 대해이 시나리오에서 마지막 매개 변수가 참이라고 가정합니다.

/* Creates an array of random integers between the range specified 
     len = length of the array you want to generate
     min = min value you require
     max = max value you require
     unique = whether you want unique or not (assume 'true' for this answer)
*/
    function _arrayRandom(len, min, max, unique) {
        var len = (len) ? len : 10,
                min = (min !== undefined) ? min : 1,
                max = (max !== undefined) ? max : 100,
                unique = (unique) ? unique : false,
                toReturn = [], tempObj = {}, i = 0;

        if(unique === true) {
            for(; i < len; i++) {
                var randomInt = Math.floor(Math.random() * ((max - min) + min));
                if(tempObj['key_'+ randomInt] === undefined) {
                    tempObj['key_'+ randomInt] = randomInt;
                    toReturn.push(randomInt);
                } else {
                    i--;
                }
            }
        } else {
            for(; i < len; i++) {
                toReturn.push(Math.floor(Math.random() * ((max - min) + min)));
            }
        }

        return toReturn;
    }

여기서 'tempObj'는 생성 된 모든 난수가이 tempObj에서 해당 키가 이미 존재하는지 직접 확인하기 때문에 매우 유용한 obj입니다. .

귀하의 경우 다음을 실행하십시오.

_arrayRandom(8, 1, 100, true);

그게 다야.


0을 포함하려면 어떻게됩니까? 줄 min = (min) ? min : 1,은 항상 1을 반환합니다 (따라서 0은 선택되지 않음)
TBE

아주 좋은 지적입니다. :). 감사합니다. 적절하게 변경했습니다. 이제 0을
전달해

2

1에서 100까지의 숫자를 섞는 것이 올바른 기본 전략이지만 8 개의 섞인 숫자 만 필요한 경우 100 개의 숫자를 모두 섞을 필요가 없습니다.

Javascript를 잘 모르지만 100 개의 null 배열을 빠르게 생성하는 것이 쉽다고 생각합니다. 그런 다음 8 라운드 동안 배열의 n 번째 요소 (0에서 시작하는 n)를 n + 1부터 99까지 임의로 선택한 요소로 바꿉니다. 물론 아직 채워지지 않은 요소는 해당 요소가 실제로 원래 인덱스에 1을 더한 값이므로 고려하기가 쉽습니다. 8 라운드를 완료하면 배열의 처음 8 개 요소에 8 개의 셔플 된 숫자가 있습니다.


2
var arr = []
while(arr.length < 8){
  var randomnumber=Math.ceil(Math.random()*100)
  if(arr.indexOf(randomnumber) === -1){arr.push(randomnumber)}  
}
document.write(arr);

내가 본 다른 답변보다 짧음


1

The Machine Charmer와 동일한 순열 알고리즘이지만 프로토 타입 구현입니다. 많은 수의 선택에 더 적합합니다. 용도 JS 1.7 destructuring 할당이 가능한 경우.

// swaps elements at index i and j in array this
// swapping is easy on js 1.7 (feature detection)
Array.prototype.swap = (function () {
    var i=0, j=1;
    try { [i,j]=[j,i]; }
    catch (e) {}
    if(i) {
        return function(i,j) {
            [this[i],this[j]] = [this[j],this[i]];
            return this;
        }
    } else {
        return function(i,j) {
            var temp = this[i];
            this[i] = this[j];
            this[j] = temp;
            return this;
        }
    }
})();


// shuffles array this
Array.prototype.shuffle = function() {
    for(var i=this.length; i>1; i--) {
        this.swap(i-1, Math.floor(i*Math.random()));
    }
    return this;
}

// returns n unique random numbers between min and max
function pick(n, min, max) {
    var a = [], i = max;
    while(i >= min) a.push(i--);
    return a.shuffle().slice(0,n);
}

pick(8,1,100);

편집 : belugabob의 답변에 따라 소수의 선택에 더 적합한 다른 제안. 고유성을 보장하기 위해 배열에서 선택한 숫자를 제거합니다.

// removes n random elements from array this
// and returns them
Array.prototype.pick = function(n) {
    if(!n || !this.length) return [];
    var i = Math.floor(this.length*Math.random());
    return this.splice(i,1).concat(this.pick(n-1));
}

// returns n unique random numbers between min and max
function pick(n, min, max) {
    var a = [], i = max;
    while(i >= min) a.push(i--);
    return a.pick(n);
}

pick(8,1,100);

좋은 재귀 구현-나는 이것이 피할 수있는 성능 적중이라고 느끼기 때문에 스플 라이스를 사용하지 않는 대안을 게시했습니다. (OP에 성능 문제가 없음)
belugabob

귀하의 솔루션은 영리하다,하지만 난 싶지 않기 때문에 내 배열 번호에서 사용할 방법을 선택하지 않습니다 내가 돌아올 때 그 요소 주위에 단행해야 할 수 있습니다.
Alsciende 2010 년

셔플하지 않으려는 배열, 원래 1-100 배열 또는 결과는 무엇입니까? 전자는 작동하는 배열이므로 중요하지 않으며 후자는 코드의 특성상 어쨌든 임의의 순서로 나옵니다. 내가 당신의 이유를 이해하는지 잘 모르겠습니다.
belugabob 2010 년

원래 하나. 유용한 일반 Array # pick 메서드를 구현했습니다. 이 함수는 이것이 작동하는 배열인지 아닌지 알지 못합니다. 일반적으로, 그것은 변경하지 않습니다 필요 이상으로.
Alsciende 2010 년

그러나이 기술을 사용할 때 비행 할 수없는 조금이라도 여전히 그것을 변경합니다.
belugabob 2010 년

1

[,2,,4,,6,7,,] 내 문제는이 구멍을 채우는 것이기 때문에 이와 같은 구멍이있는 어레이의 경우 . 그래서 내 필요에 따라 수정했습니다. :)

다음 수정 된 솔루션이 저에게 효과적이었습니다. :)

var arr = [,2,,4,,6,7,,]; //example
while(arr.length < 9){
  var randomnumber=Math.floor(Math.random()*9+1);
  var found=false;
  for(var i=0;i<arr.length;i++){
    if(arr[i]==randomnumber){found=true;break;}
  }

  if(!found)
    for(k=0;k<9;k++)
    {if(!arr[k]) //if it's empty  !!MODIFICATION
      {arr[k]=randomnumber; break;}}
}

alert(arr); //outputs on the screen

1

가장 좋은 초기 답변은 sje397 . 가능한 한 빨리 얻을 수있는 좋은 난수를 얻을 수 있습니다.

내 솔루션은 그의 솔루션과 매우 유사합니다. 그러나 때로는 임의의 숫자를 임의의 순서로 원하기 때문에 답변을 게시하기로 결정했습니다. 또한 일반적인 기능을 제공합니다.

function selectKOutOfN(k, n) {
  if (k>n) throw "k>n";
  var selection = [];
  var sorted = [];
  for (var i = 0; i < k; i++) {
    var rand = Math.floor(Math.random()*(n - i));
    for (var j = 0; j < i; j++) {
      if (sorted[j]<=rand)
        rand++;
      else
        break;
    }
    selection.push(rand);
    sorted.splice(j, 0, rand);
  }
  return selection;
}

alert(selectKOutOfN(8, 100));

1

여기에 내가 함께 만든 ES6 버전이 있습니다. 좀 더 통합 될 수 있다고 확신합니다.

function randomArray(i, min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  
  let arr = Array.from({length: i}, () => Math.floor(Math.random()* (max - min)) + min);
  
  return arr.sort();
 }
 
 let uniqueItems = [...new Set(randomArray(8, 0, 100))]
 console.log(uniqueItems);


0

어떻게 사용에 대한 해시 테이블로 개체 속성을 ? 이렇게하면 가장 좋은 시나리오는 8 번만 무작위로 추출하는 것입니다. 숫자 범위의 작은 부분을 원하는 경우에만 효과적입니다. 또한 배열에 공간을 할당 할 필요가 없기 때문에 Fisher-Yates보다 훨씬 적은 메모리 집약적입니다.

var ht={}, i=rands=8;
while ( i>0 || keys(ht).length<rands) ht[Math.ceil(Math.random()*100)]=i--;
alert(keys(ht));

그런 다음 Object.keys (obj) 가 ECMAScript 5 기능이므로 위의 내용은 현재 인터넷에서 거의 쓸모가 없다는 것을 알았습니다. 이와 같은 키 기능을 추가하여 ECMAScript 3과 호환되도록 만들었 기 때문에 두려워하지 마십시오.

if (typeof keys == "undefined") 
{ 
  var keys = function(obj) 
  {
    props=[];
    for (k in ht) if (ht.hasOwnProperty(k)) props.push(k);
    return props;
  }
}

0
var bombout=0;
var checkArr=[];
var arr=[];
while(arr.length < 8 && bombout<100){
  bombout++;
  var randomNumber=Math.ceil(Math.random()*100);
  if(typeof checkArr[randomNumber] == "undefined"){
    checkArr[randomNumber]=1;
    arr.push(randomNumber);
  }
}​

// untested - hence bombout

0

더 고유 한 경우 배열 (1..100)을 생성해야합니다.

var arr=[];
function generateRandoms(){
for(var i=1;i<=100;i++) arr.push(i);
}
function extractUniqueRandom()
{
   if (arr.length==0) generateRandoms();
   var randIndex=Math.floor(arr.length*Math.random());
   var result=arr[randIndex];
   arr.splice(randIndex,1);
   return result;

}
function extractUniqueRandomArray(n)
{
   var resultArr=[];
   for(var i=0;i<n;i++) resultArr.push(extractUniqueRandom());
   return resultArr;
}

위 코드는 더 빠릅니다 :
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]


0

JavaScript 1.6 indexOf 함수를 사용하여 동일한 코드의 다른 더 나은 버전 (수락 된 답변)을 추가합니다. 중복을 확인할 때마다 전체 어레이를 반복 할 필요가 없습니다.

var arr = []
while(arr.length < 8){
  var randomnumber=Math.ceil(Math.random()*100)
  var found=false;
    if(arr.indexOf(randomnumber) > -1){found=true;}
  if(!found)arr[arr.length]=randomnumber;
}

이전 버전의 Javascript는 여전히 맨 위에있는 버전을 사용할 수 있습니다.

추신 : 위키에 대한 업데이트를 제안하려고했지만 거부되었습니다. 나는 여전히 다른 사람들에게 유용 할 것이라고 생각합니다.


0

이것은 내 개인적인 해결책입니다.

<script>

var i, k;
var numbers = new Array();
k = Math.floor((Math.random()*8));
numbers[0]=k;
    for (var j=1;j<8;j++){
        k = Math.floor((Math.random()*8));
i=0;
while (i < numbers.length){
if (numbers[i] == k){
    k = Math.floor((Math.random()*8));
    i=0;
}else {i++;}
}
numbers[j]=k;
    }
    for (var j=0;j<8;j++){
alert (numbers[j]);
    }
</script>

8 개의 고유 한 배열 값 (0에서 7 사이)을 무작위로 생성 한 다음 경고 상자를 사용하여 표시합니다.


0
function getUniqueRandomNos() {
    var indexedArrayOfRandomNo = [];
    for (var i = 0; i < 100; i++) {
        var randNo = Math.random();
        indexedArrayOfRandomNo.push([i, randNo]);
    }
    indexedArrayOfRandomNo.sort(function (arr1, arr2) {
        return arr1[1] - arr2[1]
    });
    var uniqueRandNoArray = [];
    for (i = 0; i < 8; i++) {
        uniqueRandNoArray.push(indexedArrayOfRandomNo[i][0]);
    }
    return uniqueRandNoArray;
}

이 방법은 대부분의 답변에서 주어진 방법과 다른 것 같아서 여기에 답변을 추가 할 수 있다고 생각했습니다 (4 년 전에 질문을 받았지만).

100 개의 난수를 생성하고 각각 1에서 100까지의 숫자로 태그를 지정합니다. 그런 다음 태그가 지정된 난수를 정렬하면 태그가 무작위로 섞입니다. 또는이 질문에서 필요에 따라 태그가 지정된 난수 중 상위 8 개를 찾는 것만으로도 제거 할 수 있습니다. 상위 8 개 항목을 찾는 것이 전체 배열을 정렬하는 것보다 저렴합니다.

여기에서 정렬 알고리즘이이 알고리즘에 영향을 미친다는 점에 유의해야합니다. 사용 된 정렬 알고리즘이 안정적인 경우 더 작은 숫자를 선호하는 약간의 편향이 있습니다. 이상적으로는 정렬 알고리즘이 불안정하고 안정성 (또는 불안정성)쪽으로 치우 치지 않아 완벽하게 균일 한 확률 분포를 가진 답을 생성하는 것이 좋습니다.


0

최대 20 자리 고유 난수 생성을 처리 할 수 ​​있습니다.

JS

 var generatedNumbers = [];

    function generateRandomNumber(precision) { // input --> number precision in integer 
        if (precision <= 20) {
            var randomNum = Math.round(Math.random().toFixed(precision) * Math.pow(10, precision));
            if (generatedNumbers.indexOf(randomNum) > -1) {
                if (generatedNumbers.length == Math.pow(10, precision))
                    return "Generated all values with this precision";
                    return generateRandomNumber(precision);
            } else {
                generatedNumbers.push(randomNum);
                return randomNum;
            }
        } else
           return "Number Precision shoould not exceed 20";
    }
    generateRandomNumber(1);

여기에 이미지 설명 입력

jsFiddle


0

이 솔루션은 해시가 배열에 있는지 확인하는 것보다 훨씬 더 성능이 뛰어난 O (1)를 사용합니다. 추가 안전 검사도 있습니다. 도움이되기를 바랍니다.

function uniqueArray(minRange, maxRange, arrayLength) {
  var arrayLength = (arrayLength) ? arrayLength : 10
  var minRange = (minRange !== undefined) ? minRange : 1
  var maxRange = (maxRange !== undefined) ? maxRange : 100
  var numberOfItemsInArray = 0
  var hash = {}
  var array = []

  if ( arrayLength > (maxRange - minRange) ) throw new Error('Cannot generate unique array: Array length too high')

  while(numberOfItemsInArray < arrayLength){
    // var randomNumber = Math.floor(Math.random() * (maxRange - minRange + 1) + minRange)
    // following line used for performance benefits
    var randomNumber = (Math.random() * (maxRange - minRange + 1) + minRange) << 0

    if (!hash[randomNumber]) {
      hash[randomNumber] = true
      array.push(randomNumber)
      numberOfItemsInArray++
    }
  }
  return array
}
document.write(uniqueArray(1, 100, 8))

0

이것을 생성기로 구현하면 작업하기가 매우 좋습니다. 이 구현은 전체 입력 배열을 먼저 셔플해야하는 구현과 다릅니다.

sample기능은 느리게 작동 하여 요청한 항목 까지 반복 당 1 개의 무작위 항목을 제공합니다 N. 1000 개 목록에서 3 개 항목 만 원하면 1000 개 항목을 모두 터치 할 필요가 없기 때문에 좋습니다.

// sample :: Integer -> [a] -> [a]
const sample = n => function* (xs) {
  let ys = xs.slice(0);
  let len = xs.length;
  while (n > 0 && len > 0) {
    let i = (Math.random() * len) >> 0;
    yield ys.splice(i,1)[0];
    n--; len--;
  }
}

// example inputs
let items = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
let numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

// get 3 random items
for (let i of sample(3) (items))
  console.log(i); // f g c

// partial application
const lotto = sample(3);
for (let i of lotto(numbers))
  console.log(i); // 3 8 7

// shuffle an array
const shuffle = xs => Array.from(sample (Infinity) (xs))
console.log(shuffle(items)) // [b c g f d e a]

sample입력 배열을 변경하지 않는 방식 으로 구현하기로 선택 했지만 변경 구현이 유리하다고 쉽게 주장 할 수 있습니다.

예를 들어, shuffle함수는 원래 입력 배열을 변경하려고 할 수 있습니다. 또는 동일한 입력에서 여러 번 샘플링하여 매번 입력을 업데이트 할 수 있습니다.

// sample :: Integer -> [a] -> [a]
const sample = n => function* (xs) {
  let len = xs.length;
  while (n > 0 && len > 0) {
    let i = (Math.random() * len) >> 0;
    yield xs.splice(i,1)[0];
    n--; len--;
  }
}

// deal :: [Card] -> [Card]
const deal = xs => Array.from(sample (2) (xs));

// setup a deck of cards (13 in this case)
// cards :: [Card]
let cards = 'A234567890JQK'.split('');

// deal 6 players 2 cards each
// players :: [[Card]]
let players = Array.from(Array(6), $=> deal(cards))

console.log(players);
// [K, J], [6, 0], [2, 8], [Q, 7], [5, 4], [9, A]

// `cards` has been mutated. only 1 card remains in the deck
console.log(cards);
// [3]

sample배열 입력 변이로 인해 더 이상 순수한 함수가 아니지만 특정 상황 (위에서 설명)에서는 더 의미가있을 수 있습니다.


배열을 반환하는 함수 대신 생성기를 선택한 또 다른 이유는 특정 조건까지 샘플링을 계속할 수 있기 때문입니다.

1,000,000 개의 난수 목록에서 첫 번째 소수를 원할 것입니다.

  • "몇 개를 샘플링해야합니까?" – 당신은 지정할 필요가 없습니다
  • "먼저 모든 소수를 찾은 다음 임의의 소수를 선택해야합니까?" -아니.

생성기로 작업하고 있기 때문에이 작업은 간단합니다.

const randomPrimeNumber = listOfNumbers => {
  for (let x of sample(Infinity) (listOfNumbers)) {
    if (isPrime(x))
      return x;
  }
  return NaN;
}

이것은 한 번에 하나의 난수를 연속적으로 샘플링 x하고 소수인지 확인한 다음 반환 x됩니다. 소수를 찾기 전에 숫자 목록이 소진되면을 NaN반환합니다.


노트 :

이 답변 은 원래이 질문의 중복으로 마감 된 다른 질문에 공유되었습니다. 여기에 제공된 다른 솔루션과 매우 다르기 때문에 여기에서도 공유하기로 결정했습니다.


0
getRandom (min, max) {
  return Math.floor(Math.random() * (max - min)) + min
}

getNRandom (min, max, n) {
  const numbers = []
  if (min > max) {
    return new Error('Max is gt min')
  }

  if (min === max) {
    return [min]
  }

  if ((max - min) >= n) {
    while (numbers.length < n) {
      let rand = this.getRandom(min, max + 1)
      if (numbers.indexOf(rand) === -1) {
        numbers.push(rand)
      }
    }
  }

  if ((max - min) < n) {
    for (let i = min; i <= max; i++) {
      numbers.push(i)
    }
  }
  return numbers
}

0

a를 사용하는 Set것이 가장 빠른 옵션입니다. 다음은 콜백 생성기를 사용하는 고유 한 랜덤을 가져 오는 일반 함수입니다. 지금은의 빠른재사용 .

// Get a unique 'anything'
let unique = new Set()

function getUnique(generator) {
  let number = generator()
  while (!unique.add(number)) {
    number = generator()
  }
  return number;
}

// The generator.  Return anything, not just numbers.
const between_1_100 = () => 1 + Math.floor(Math.random() * 100)

// Test it
for (var i = 0; i < 8; i++) {
  const aNumber = getUnique(between_1_100)
}
// Dump the 'stored numbers'
console.log(Array.from(unique))


0

이것은 Fisher Yates / Durstenfeld Shuffle 의 구현 이지만 실제로 배열을 생성하지 않으므로 사용 가능한 요소 수에 비해 선택 크기가 작은 경우 필요한 공간 복잡성이나 메모리가 줄어 듭니다.

100에서 8 개의 숫자를 선택하기 위해 100 개의 요소로 구성된 배열을 만들 필요가 없습니다.

어레이가 생성되었다고 가정하면,

  • array (100) 끝에서 난수 (rnd 에서 1부터 100까지 )를
  • 100과 난수를 바꿉니다. rnd
  • array (99)로 1 단계를 반복합니다.

배열이 생성되지 않은 경우 hashMap을 사용하여 실제 교체 된 위치를 기억할 수 있습니다. 생성 된 두 번째 난수가 이전에 생성 된 숫자 중 하나와 같으면 맵은 실제 값이 아닌 해당 위치의 현재 값을 제공합니다.

const getRandom_ = (start, end) => {
  return Math.floor(Math.random() * (end - start + 1)) + start;
};
const getRealValue_ = (map, rnd) => {
  if (map.has(rnd)) {
    return getRealValue_(map, map.get(rnd));
  } else {
    return rnd;
  }
};
const getRandomNumbers = (n, start, end) => {
  const out = new Map();
  while (n--) {
    const rnd = getRandom_(start, end--);
    out.set(getRealValue_(out, rnd), end + 1);
  }
  return [...out.keys()];
};

console.info(getRandomNumbers(8, 1, 100));
console.info(getRandomNumbers(8, 1, Math.pow(10, 12)));
console.info(getRandomNumbers(800000, 1, Math.pow(10, 15)));


0

다음은 중복없이 0에서 100 (0과 100 모두 포함) 범위에서 가져온 난수 5 개의 숫자의 예입니다.

let finals = [];
const count = 5; // Considering 5 numbers
const max = 100;

for(let i = 0; i < max; i++){
  const rand = Math.round(Math.random() * max);
  !finals.includes(rand) && finals.push(rand)
}

finals = finals.slice(0, count)

-1

다음과 같이 하나의 라이너로도 할 수 있습니다.

[...((add, set) => add(set, add))((set, add) => set.size < 8 ? add(set.add(Math.floor(Math.random()*100) + 1), add) : set, new Set())]


아무것도 할당하지 않는 순수함을 위해.
Marcin Król
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.