Javascriptオブジェクトからランダムなプロパティを選択します


89

{'cat': 'meow'、 'dog': 'woof' ...}のようなJavascriptオブジェクトがあるとします。私が思いついたこの長く曲がりくねった方法よりも、オブジェクトからランダムなプロパティを選択するより簡潔な方法はありますか? :

function pickRandomProperty(obj) {
    var prop, len = 0, randomPos, pos = 0;
    for (prop in obj) {
        if (obj.hasOwnProperty(prop)) {
            len += 1;
        }
    }
    randomPos = Math.floor(Math.random() * len);
    for (prop in obj) {
        if (obj.hasOwnProperty(prop)) {
            if (pos === randomPos) {
                return prop;
            }
            pos += 1;
        }
    }       
}

OP、選択した回答を再選択してください... @ kennytmは他の人より先に正しく回答しました。デビッドの答えは単に悪いコーディングです(それは機能しますが)
vsync 2018

質問と回答は、質問のタイトルが示すようにランダムなプロパティではなく、ランダムなオブジェクトプロパティのを返すことを実際に探していることに注意してください。
kontur

回答:


182

選択した答えはうまくいきます。ただし、この回答はより高速に実行されます。

var randomProperty = function (obj) {
    var keys = Object.keys(obj);
    return obj[keys[ keys.length * Math.random() << 0]];
};

3
ループを使用しないため、これは優れています
Dominic

14
私はいくつかのテストを行いましたが、選択した回答は問題なく機能し、プロパティの選択には偏りがないようです(回答間の推測とは異なります)。ただし、170,000キーのオブジェクトでテストしたところ、ここでのソリューションは、選択したソリューションの約2倍の速さでした。
トンボ2014年

8
<< 0(0だけ左にビットシフト)はMath.round()を書くための簡略化されたメソッドですか?
SystemicPlural

4
このjsperfjsperf.com/random-object-property-selection は、この回答と選択された回答のベンチマークを行います。この回答は、小さいオブジェクト(100プロパティ)の場合、パフォーマンスが3倍向上します。より大きなオブジェクト(100kプロパティ)では、差は2倍良くなります。
constablebrew 2015年

2
@ MuhammadUmer-No Math.random()。は[0,1)の範囲の数値を返します。
Yay295 2015

74

ストリームからランダムな要素を選択する

function pickRandomProperty(obj) {
    var result;
    var count = 0;
    for (var prop in obj)
        if (Math.random() < 1/++count)
           result = prop;
    return result;
}

2
ECMAScript標準は、常に同じ順序でトラバースされるプロパティについて何かを述べていますか?ほとんどの実装内のオブジェクトは、安定した秩序を持っていますが、動作は仕様で定義されていない:stackoverflow.com/questions/280713/...
ブレンダン・ベルク

4
これは、オブジェクトの最初の要素に向かって偏っているようです。理由はまだわかりません!
コールグリーソン2014年

7
これにより、最初のプロパティが選択されることはなく(Math.randomは常に<1)、その後、各番号が選択される可能性は0.5になります。などの第四のための第三のための第二の特性のための0.5、0.25、0.125だから、
SystemicPlural

4
いくつかの修正:この関数は最初のプロパティを選択できます。最初の反復では、カウントのプレフィックス増分により、方程式の右辺が1/1 == 1と評価されます。Math.randomは常に[0,1)(0から1、1を除く)の範囲にあるため、式はtrueと評価され、最初のプロパティが選択されます。ランダム選択の分布に関しては、均一です。1つのプロパティで、100%の確率で選択されます。2つで、どちらかが選択される可能性が50%あります。3つで33.3%。等々。このソリューションのメモリフットプリントは最小限です。
constablebrew 2015年

3
@ davidhadas3つの要素のシーケンスについて考えてみます。最初の要素は確率1で選択されます。ただし、確率1/2の2番目の要素に置き換えられる可能性があります(すぐには戻らないことに注意してください)。次に、2番目の要素が1/3の確率で3番目の要素に置き換えられる可能性があります。したがって、P(最初)= P(最初に選択された)* P(2番目に選択されていない)* P(3番目に選択されていない)= 1 * 1/2 * 2/3 = 1/3; P(2番目)= P(2番目に選択)* P(3番目に選択されていない)= 1/2 * 1/3 = 1/3; P(3番目)= P(3番目に選択)= 1/3。
マーティンTörnwall

19

どの例も十分に混乱しているとは思わなかったので、同じことをしている例を読むのは本当に難しいです。

編集:同僚に嫌われてほしくない限り、おそらくこれを行うべきではありません。

var animals = {
    'cat': 'meow',
    'dog': 'woof',
    'cow': 'moo',
    'sheep': 'baaah',
    'bird': 'tweet'
};

// Random Key
console.log(Object.keys(animals)[Math.floor(Math.random()*Object.keys(animals).length)]);

// Random Value
console.log(animals[Object.keys(animals)[Math.floor(Math.random()*Object.keys(animals).length)]]);

説明:

// gets an array of keys in the animals object.
Object.keys(animals) 

// This is a number between 0 and the length of the number of keys in the animals object
Math.floor(Math.random()*Object.keys(animals).length)

// Thus this will return a random key
// Object.keys(animals)[0], Object.keys(animals)[1], etc
Object.keys(animals)[Math.floor(Math.random()*Object.keys(animals).length)]

// Then of course you can use the random key to get a random value
// animals['cat'], animals['dog'], animals['cow'], etc
animals[Object.keys(animals)[Math.floor(Math.random()*Object.keys(animals).length)]]

長い手で、混乱が少ない:

var animalArray  = Object.keys(animals);
var randomNumber = Math.random();
var animalIndex  = Math.floor(randomNumber * animalArray.length);

var randomKey    = animalArray[animalIndex];
// This will course this will return the value of the randomKey
// instead of a fresh random value
var randomValue  = animals[randomKey]; 

4
これは実際に最も合理的な解決策である
パヴェル

2
私はこれが最も好きで、説明とすべてがあり、実際の例のPOJOも含まれています。素晴らしい答え、もっと賛成するに値する!すべてがとても理解しやすくなります!
Tigerrrrr

1
最善の解決策!これは最も投票されるべきです。
nilsoviani

15

オブジェクトを歩きながら、キーの配列を作成するだけです。

var keys = [];
for (var prop in obj) {
    if (obj.hasOwnProperty(prop)) {
        keys.push(prop);
    }
}

次に、キーから要素をランダムに選択します。

return keys[keys.length * Math.random() << 0];

13
Object.keysはここで役立ちますvar keys = Object.keys(obj)
whadar 2013年

Dang <<は、Math.floor()を使用するよりもはるかに優雅で、おそらく安価でもあります。私は本当に降りて、それらのビット演算子の使い方を学ばなければなりません。
ポールJ

5
この場合、ビット演算子の使用はハッキングである可能性が高くなります。入力として整数が必要なため、数値を変換します。<< 0整数に適用しても何も起こりません。parseInt()同じ仕事をします。したがって、理解しにくいコードを書く以外に、ここで学ぶことは何もありません。
ランドアンダー2017

13

ライブラリを使用できる場合は、Lo- DashJSライブラリにそのような場合に非常に役立つメソッドがたくさんあることに気付くかもしれません。この場合は、先に進んで確認してください_.sample()

(Lo-Dash規則では、ライブラリオブジェクトに_という名前が付けられていることに注意してください。同じページでインストールを確認して、プロジェクトに設定することを忘れないでください。)

_.sample([1, 2, 3, 4]);
// → 2

あなたの場合、先に進んで使用してください:

_.sample({
    cat: 'meow',
    dog: 'woof',
    mouse: 'squeak'
});
// → "woof"

3

underscore.jsを使用している場合は、次のことができます。

_.sample(Object.keys(animals));

追加:

複数のランダムなプロパティが必要な場合は、番号を追加します。

_.sample(Object.keys(animals), 3);

これらのランダムなプロパティのみを持つ新しいオブジェクトが必要な場合:

const props = _.sample(Object.keys(animals), 3);
const newObject = _.pick(animals, (val, key) => props.indexOf(key) > -1);

0

これを行う別の簡単な方法は、関数を適用する関数を定義することMath.random()です。

この関数は、「min」からの範囲のランダムな整数を返します

function getRandomArbitrary(min, max) {
  return Math.floor(Math.random() * (max - min) + min);
}

次に、上記の関数をパラメーターとして指定するたびに、Javascriptオブジェクトから「キー」または「値」または「両方」を抽出します。

var randNum = getRandomArbitrary(0, 7);
var index = randNum;
return Object.key(index); // Returns a random key
return Object.values(index); //Returns the corresponding value.

Object.values(someObject)[index]のことですか?
Bemmu

インデックスIが生成される格納するために使用したことの変数のランダムな数だけ、コンテナ、何も特別なものです。生成された数値を別の変数に格納しなかった場合、関数の各インスタンスは、getRandomArbitrary呼び出されるたびに新しい乱数を生成します。
Sushant Chaudhary 2018

0

JSONオブジェクトには、次のものを配置する必要があります。

var object={
  "Random": function() {
    var result;
    var count = 0;
    for (var prop in this){
      if (Math.random() < 1 / ++count&&prop!="Random"){
        result = this[prop];
      }
    }
    return result;
  }
}

その関数は、ランダムなプロパティの内部を返します。


0

次のコードを使用して、JavaScriptオブジェクトからランダムなプロパティを選択できます。

function randomobj(obj) {
var objkeys = Object.keys(obj)
return objkeys[Math.floor(Math.random() * objkeys.length)]
}
var example = {foo:"bar",hi:"hello"}
var randomval = example[randomobj(example)] // will return to value
// do something

このコードは質問に答えることができますが、問題を解決する方法や理由に関する追加のコンテキストを提供すると、回答の長期的な価値が向上します。
nic3500 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.