JavaScript配列からランダムな値を取得する


794

検討してください:

var myArray = ['January', 'February', 'March'];    

JavaScriptを使用してこの配列からランダムな値を選択するにはどうすればよいですか?

回答:


1481

シンプルなワンライナーです

const randomElement = array[Math.floor(Math.random() * array.length)];

const months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
const randomMonth = months[Math.floor(Math.random() * months.length)];

console.log("random month =>", randomMonth);


9
@SapphireSunこれは正しいです。Math.floor(Math.random(...))切り捨てられる呼び出しに注意してください。
ashes999 2014年

33
ああ、私は何か新しいことを学びました。私はそれが正確に1に等しい場合について議論していましたが、明らかに(W3Schoolsによると)Math.randomは0を含み1を含みません。私の悪い。
SapphireSun

13
私は間違っているかもしれませんが、var rand = myArray[Math.random() * myArray.length>>0]少し速いことを思い出します
vrugtehagel

6
すでにlodashを使用している場合は、念のために、あなたは(配列)_.sample使用することができます
ガブリエルMatusevich

2
私はこのバリアントを好む:var rand = myArray[Math.random() * myArray.length | 0]
ニコラス

76

プロジェクトにアンダースコアまたはロダッシュがすでに含まれている場合は、を使用できます_.sample

// will return one item randomly from the array
_.sample(['January', 'February', 'March']);

複数のアイテムをランダムに取得する必要がある場合は、アンダースコアの2番目の引数として渡すことができます。

// will return two items randomly from the array using underscore
_.sample(['January', 'February', 'March'], 2);

または_.sampleSizelodashでメソッドを使用します:

// will return two items randomly from the array using lodash
_.sampleSize(['January', 'February', 'March'], 2);

typescriptを使用する場合:戻り値の型は、文字列配列が指定された "string"ではなく "string | undefined"になることに注意してください。
Stephan Schielke

23

プロトタイプメソッド

ランダムな値をたくさん取得することを計画している場合は、その関数を定義することをお勧めします。

まず、これをコードのどこかに配置します。

Array.prototype.sample = function(){
  return this[Math.floor(Math.random()*this.length)];
}

今:

[1,2,3,4].sample() //=> a random element

CC0 1.0ライセンスの条件に基づいてパブリックドメインにリリースされたコード。


そして、これは何をしますか?
ケンシャープ

3
@KenSharpを使用すると.sample()、任意の配列を呼び出してランダムなアイテムを取得できます
Ben Aubin

5
ネイティブオブジェクトタイプの拡張は避けてください。私は自分の回答を削除しました。多くの賛成意見が出ているのを見て、悪い習慣を促進しています。この問題の詳細については、たとえば、stackoverflow.com / questions
Markus Amalthea Magnuson

20

~~はよりもはるかに高速でMath.Floor()あるため、UI要素を使用して出力を生成する際のパフォーマンスの最適化に関しては~~、ゲームに勝ちます。より詳しい情報

var rand = myArray[~~(Math.random() * myArray.length)];

しかし、Math.Floor()ビット単位演算子が大きな数で奇妙に動作するため、配列に何百万もの要素が含まれることがわかっている場合は、ビット単位演算子との間で再考した方がよいかもしれません。出力で説明されている以下の例を参照してください。より詳しい情報

var number = Math.floor(14444323231.2); // => 14444323231
var number = 14444323231.2 | 0; // => 1559421343

1
リンクは死んでいるが、興味深い投稿であり、私はこれを今よりもっと使うMath.floor
つもりだ

1
「ビットごとのnot」演算子を使用すると、高速ではありますが、読みにくいため、自分にとってより重要なものを選択する必要があります
MaciejUrbański'29

16

前回とは異なるランダムなアイテムを選択したいとします(実際にはランダムではありませんが、それでも一般的な要件です)...

@Markusの回答に基づいて、別のプロトタイプ関数を追加できます。

Array.prototype.randomDiffElement = function(last) {
   if (this.length == 0) {
      return;
   } else if (this.length == 1) {
      return this[0];
   } else {
      var num = 0;
      do {
         num = Math.floor(Math.random() * this.length);
      } while (this[num] == last);
      return this[num];
   }
}

そしてそのように実装します:

var myRandomDiffElement = myArray.randomDiffElement(lastRandomElement)

11

固定値(月の名前のリストなど)があり、1行のソリューションが必要な場合

var result = ['January', 'February', 'March'][Math.floor(Math.random() * 3)]

配列の2番目の部分は、JavaScriptで[5,6,8,7] [1,2] = 8を使用する理由で説明されているアクセス操作です。


2
このようなコードは、悪質で有害な慣行です。本番環境では使用しないでください。可読性が低く、配列の長さがハードコードされています。配列の入力を変更する人は、最後にハードコードされた長さを編集するのを忘れているかもしれません。
カモメ

@Seagull OPが特定の環境を要求することはありません。また、このコメントは、この質問のほとんどすべての回答に適用できるため、意味がありません;)
IG Pascual

しかし、ほとんどの人はGoogle検索からこの質問にたどり着き、元のOP以外のシナリオでソリューションを使用する可能性があります。
カモメ

@Seagull Hahaの人々は、どのアプローチを使用するかを自由に決定できます。私はクリーンなコードガイドラインのFAQではありません!
IG Pascual 2018

10

最短バージョン:

var myArray = ['January', 'February', 'March']; 
var rand = myArray[(Math.random() * myArray.length) | 0]

何をし| 0ますか?
Ken Sharp

2
Math.floorと同じように、FloatをIntに変えます。
foxiris

4
@KenSharp | 0自体は何もしないビット単位の演算ですが、JavaScriptでは浮動小数点はビット単位の演算の前にintに変換されます。つまり、これ+ ''は実際には何もしない方法ですが、文字列に変換するために使用できます。
dshepherd '19

それは同じMath.floorではありませんが、ここで行うのは正しいことです。これは演算子なので、Math.floorコードの実行中にいつでも実行できMath.floor = someOtherFunction、 '|'に対して同じことを実行できないので、場合よりも高速です。一方などのためMath.floor|さまざまな試みているMath.floor(-1.5)-1.5 | 0。ちなみに括弧は必要ありません。|優先度は非常に低くなっています。
gman

7

Pascualのソリューションのように1行で記述したい場合は、ES6のfind関数を使用してそれを記述します(nアイテムから1つをランダムに選択する確率はであるという事実に基づいています1/n)。

var item = ['A', 'B', 'C', 'D'].find((_, i, ar) => Math.random() < 1 / (ar.length - i));
console.log(item);

テストの目的で、別の変数にのみ配列を保存しない正当な理由がある場合は、このアプローチを使用してください。それ以外の場合は、他の答え(floor(random()*lengthおよび別の関数を使用)を使用する方法です。


非常に独自のソリューション。よくやった!ちなみに、ここで唯一のリアルでダイナミックなワンライナーソリューション。
Slavik Meltser

7

Faker.jsには、ランダムなテストデータを生成するための多くのユーティリティ関数があります。これは、テストスイートのコンテキストでは適切なオプションです。

const Faker = require('faker');
Faker.random.arrayElement(['January', 'February', 'March']);

コメンターが述べたように、通常はこのライブラリを製品コードで使用しないでください。


8
このような単純な問題の場合、ライブラリ全体の依存関係を追加する必要はなく、コードの膨張につながります。どちらかと言えばFaker、ランダムな配列要素を選択する実際の方法をお勧めします。
Pixxl 2017

1
このような「単純な問題」は、通常、ライブラリによって解決されます。ライブラリは、数百人がすでに直面している問題の単純な解決策を提供します。これらのライブラリは通常、堅牢で十分にデバッグされており、再実装したくないさまざまな警告に対処します。通常は、ライブラリを使用することをお勧めします。
smonff 2018年

あなただけのライブラリーからその1つの方法をコピーして、utilsのファイルにそれを置く必要があるよりも、
リックBross氏

ライブラリをWebブラウザーに出荷するときに、WRTページのコスト/利益を評価する必要があるという助言は堅実なアドバイスであり、ブラウザーにFaker.jsを出荷するのはばかげていることに心から同意します。ただし、質問では、どのJSランタイムが使用されているかについては触れられていません。NodeJSベースのランタイムの場合、依存関係は完全に妥当です。これは、Cucumber JSテストスイートでFaker.jsを使用している場合に当てはまります。
ネイサン、

6

Arrayプロトタイプを編集することは有害な場合があります。これは、仕事をするための簡単な機能です。

function getArrayRandomElement (arr) {
  if (arr && arr.length) {
    return arr[Math.floor(Math.random() * arr.length)];
  }
  // The undefined will be returned if the empty array was passed
}

使用法:

// Example 1
var item = getArrayRandomElement(['January', 'February', 'March']);

// Example 2
var myArray = ['January', 'February', 'March'];
var item = getArrayRandomElement(myArray);

3

任意の数のアイテムを返すことができる再帰的なスタンドアロン関数(lodash.sampleSizeと同じ):

function getRandomElementsFromArray(array, numberOfRandomElementsToExtract = 1) {
    const elements = [];

    function getRandomElement(arr) {
        if (elements.length < numberOfRandomElementsToExtract) {
            const index = Math.floor(Math.random() * arr.length)
            const element = arr.splice(index, 1)[0];

            elements.push(element)

            return getRandomElement(arr)
        } else {
            return elements
        }
    }

    return getRandomElement([...array])
}

2

取得するには暗号強いランダムアイテムフォームの配列を使用します

let rndItem = a=> a[rnd()*a.length|0];
let rnd = ()=> crypto.getRandomValues(new Uint32Array(1))[0]/2**32;

var myArray = ['January', 'February', 'March'];

console.log( rndItem(myArray) )


1

これは、@ Jacob Relkinのソリューションに似ていますが、より一般的です。

これはES2015です。

const randomChoice = arr => {
    const randIndex = Math.floor(Math.random() * arr.length);
    return arr[randIndex];
};

コードは、0と配列の長さの間の乱数を選択し、そのインデックスでアイテムを返すことによって機能します。


1

var item = myArray[Math.floor(Math.random()*myArray.length)];

または同等の短いバージョン:

var item = myArray[(Math.random()*myArray.length)|0];

サンプルコード:

var myArray = ['January', 'February', 'March'];    
var item = myArray[(Math.random()*myArray.length)|0];
console.log('item:', item);


1

シンプルな機能:

var myArray = ['January', 'February', 'March'];
function random(array) {
     return array[Math.floor(Math.random() * array.length)]
}
random(myArray);

または

var myArray = ['January', 'February', 'March'];
function random() {
     return myArray[Math.floor(Math.random() * myArray.length)]
}
random();

または

var myArray = ['January', 'February', 'March'];
function random() {
     return myArray[Math.floor(Math.random() * myArray.length)]
}
random();

グローバルネームスペースを汚染しないように、関数内でmyArrayy変数を設定することをお勧めします。
Neil Meyer

0

私の意見では、プロトタイプをいじり回したり、適切なタイミングで宣言したりするよりも、ウィンドウに公開することをお勧めします。

window.choice = function() {
  if (!this.length || this.length == 0) return;
  if (this.length == 1) return this[0];
  return this[Math.floor(Math.random()*this.length)];
}

アプリのどこでも、次のように呼び出します。

var rand = window.choice.call(array)

これにより、for(x in array)ループを適切に使用できます


1
誰かがそれを反対票を投じたときは私はここにいなかったし、反対票を投じなかったが、ウィンドウに公開することは基本的にグローバル変数を宣言していると思う。参照:stackoverflow.com/questions/2613310/...
クリス・

1
for...in配列、または一般的には使用しないでください。あなたはプロトタイプチェーンを歩く危険を冒します。また、配列のすべてのインデックスではなく、オブジェクトのすべてのプロパティを対象としています。配列でイテレータを使用する場合は、を使用しますfor (var i = 0; i < foo.length; i++){}。さらに、Array.prototype.forEach代わりに何かを使用してください。
Robert

1
グローバルスコープを汚染するため、私はこれを好みません。そこにいるのはこれだけかもしれませんが、その良い習慣に違反する習慣を与えます。
Jekk 2016年

0

変数randをmyArray [];の呼び出し内に表示できるようにする別の変数に連結するだけで、トップアンサーの複雑さを回避する方法を見つけました。作成された新しい配列を削除し、その複雑さをいじくり回すことによって、私は実用的な解決策を思いつきました:

<!DOCTYPE html>
<html>
<body>

<p id="demo"></p>

<script>

var myArray = ['January', 'February', 'March', 'April', 'May'];    

var rand = Math.floor(Math.random() * myArray.length);

var concat = myArray[rand];

function random() {
   document.getElementById("demo").innerHTML = (concat);
}
</script>

<button onClick="random();">
Working Random Array generator
</button>

</body>
</html>

なぜconcatここで変化しているのか混乱しています... randomそれ自体は変化しておらず、他に何回も呼び出されていません...
BalinKingOfMoria Reinstate CMs

1
このソリューションは完全に意味をなさない。concatという変数を作成するのはなぜですか?
超光速

0

static generateMonth() { 
const theDate = ['January', 'February', 'March']; 
const randomNumber = Math.floor(Math.random()*3);
return theDate[randomNumber];
};

定数変数を配列に設定すると、配列内の3つのオブジェクトからランダムに選択する別の定数が得られ、関数は結果を返すだけです。


-1

ランダムな要素を取得する一般的な方法:

let some_array = ['Jan', 'Feb', 'Mar', 'Apr', 'May'];
let months = random_elems(some_array, 3);

console.log(months);

function random_elems(arr, count) {
  let len = arr.length;
  let lookup = {};
  let tmp = [];

  if (count > len)
    count = len;

  for (let i = 0; i < count; i++) {
    let index;
    do {
      index = ~~(Math.random() * len);
    } while (index in lookup);
    lookup[index] = null;
    tmp.push(arr[index]);
  }

  return tmp;
}


-1

randojsは、これをもう少しシンプルで読みやすくします。

console.log( rando(['January', 'February', 'March']).value );
<script src="https://randojs.com/1.0.0.js"></script>


1
ちょうど好奇心が強い:なぜ反対票?
Leponzo

1
一部の人々は、たとえそれが物事をより速く、より読みやすくするとしても、自分で書くことができるコードをライブラリで調達するのが好きではありません。ライブラリが何らかの理由でダウンした場合、あなたのウェブサイトに不具合が生じています。randojsはダウンしませんが、たとえばjQueryのようなライブラリーとしてはあまり知られていないため、彼らはそれを知りません
Aaron Plocharczyk

-2

これを行う方法の例を次に示します。

$scope.ctx.skills = data.result.skills;
    $scope.praiseTextArray = [
    "Hooray",
    "You\'re ready to move to a new skill", 
    "Yahoo! You completed a problem", 
    "You\'re doing great",  
    "You succeeded", 
    "That was a brave effort trying new problems", 
    "Your brain was working hard",
    "All your hard work is paying off",
    "Very nice job!, Let\'s see what you can do next",
    "Well done",
    "That was excellent work",
    "Awesome job",
    "You must feel good about doing such a great job",
    "Right on",
    "Great thinking",
    "Wonderful work",
    "You were right on top of that one",
    "Beautiful job",
    "Way to go",
    "Sensational effort"
  ];

  $scope.praiseTextWord = $scope.praiseTextArray[Math.floor(Math.random()*$scope.praiseTextArray.length)];


-3

1つのランダムな値を作成して配列に渡す

次のコードを試してください。

//For Search textbox random value
var myPlaceHolderArray = ['Hotels in New York...', 'Hotels in San Francisco...', 'Hotels Near Disney World...', 'Hotels in Atlanta...'];
var rand = Math.floor(Math.random() * myPlaceHolderArray.length);
var Placeholdervalue = myPlaceHolderArray[rand];

alert(Placeholdervalue);

5
この回答は、すでに受け入れられている回答と同じソリューションを使用しています。同じソリューションを2回追加することは控え、代わりに、会話に貢献する可能性のある他の可能な選択肢のみを提示してください。
Pixxl 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.