Bir Javascript nesnesinden rastgele özellik seçin


90

{'Cat': 'meow', 'dog': 'woof' gibi bir Javascript nesneniz olduğunu varsayalım ...} Nesneden rastgele bir özellik seçmenin bu uzun soluklu yoldan daha kısa bir yolu var mı? :

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, lütfen seçtiğiniz cevabı tekrar seçin ... @kennytm diğerlerinden önce doğru cevapladı. David'in cevabı basitçe kötü kodlama (işe
yarasa da

Soru ve yanıtların aslında soru başlığının önerdiği gibi rastgele bir özelliği değil, rastgele bir nesne özelliğinin değerini döndürmeyi aradığını unutmayın.
kontur

Yanıtlar:


184

Seçilen cevap iyi sonuç verecektir. Ancak, bu cevap daha hızlı çalışacaktır:

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

3
döngü kullanmadığı için bu daha iyi
Dominic

14
Bazı testler yaptım ve öyle görünüyor ki seçilen cevap gayet iyi çalışıyor ve mülkiyet seçiminin tarafsız olduğu (cevaplar arasındaki spekülasyonların aksine); ancak 170.000 tuşlu bir nesne üzerinde test ettim ve buradaki çözüm, seçilen çözümden yaklaşık iki kat daha hızlıydı.
Yusufçuk

8
<< 0 (0 ile sola bit kaydırma) Math.round () yazmanın kısa bir yöntemi midir?
SystemicPlural

4
Bu jsperf jsperf.com/random-object-property- seçimi, bu yanıtı ve seçilen yanıtı karşılaştırır. Bu yanıt, daha küçük nesneler (100 özellik) için 3 kat daha iyi performans gösterir. Daha büyük nesneler (100k özellik), fark 2 kat daha iyi düşer.
Constablebrew

2
@MuhammadUmer - No. Math.random(), [0,1) aralığında bir sayı döndürür.
Yay295

74

Bir akıştan rastgele bir öğe seçme

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

2
ECMAScript standardı, özelliklerin her zaman aynı sırayla geçilmesi hakkında bir şey söylüyor mu? Çoğu uygulamadaki nesnelerin kararlı sıralaması vardır, ancak davranış spesifikasyonda tanımsızdır: stackoverflow.com/questions/280713/…
Brendan Berg

4
Bu, nesnedeki ilk öğeye doğru bir eğime sahip gibi görünüyor. Henüz nedenini anlamadım!
Cole Gleason

7
Bu asla ilk özelliği seçmez (Math.random her zaman <1'dir) ve bundan sonra her sayının seçilme şansı 0,5 olacaktır. Öyleyse, ikinci mülk için 0,5, 3 için 0,25, 4 için 0,125 vb.
SystemicPlural

4
Bazı düzeltmeler: Bu işlev ilk özelliği seçebilir. İlk yinelemede, sayıdaki önek artışı denklemin sağ tarafının 1/1 == 1 olarak değerlendirilmesini sağlar. Math.random her zaman [0,1) aralığında olduğundan (sıfırdan bire, bir hariç), ifade, doğru olarak değerlendirilir ve ilk özellik seçilir. Rastgele seçimin dağılımı söz konusu olduğunda, tekdüzedir. Bir mülkle seçilme şansı% 100'dür. İki ile% 50 olasılıkla seçilecektir. Üç ile% 33,3. Ve bunun gibi. Bu çözüm, minimum bellek ayak izine sahiptir.
Constablebrew

3
@davidhadas Üç öğeden oluşan bir dizi düşünün. İlki 1 olasılıkla seçilir. Ancak, 1/2 olasılıkla ikinci öğe ile değiştirilebilir (hemen dönmeyeceğimize dikkat edin!). İkinci element, 1/3 olasılıkla üçüncü element ile değiştirilebilir. Böylece P (birinci) = P (ilk seçilen) * P (ikinci alınmadı) * P (üçüncü seçilmedi) = 1 * 1/2 * 2/3 = 1/3; P (saniye) = P (ikinci seçildi) * P (üçüncü seçilmedi) = 1/2 * 1/3 = 1/3; P (üçüncü) = P (üçüncü seçilen) = 1/3.
Martin Törnwall

19

Örneklerin hiçbirinin yeterince kafa karıştırıcı olduğunu düşünmedim, bu yüzden burada aynı şeyi yapan okuması gerçekten zor bir örnek var.

Düzenleme: İş arkadaşlarınızın sizden nefret etmesini istemediğiniz sürece muhtemelen bunu yapmamalısınız.

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)]]);

Açıklama:

// 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)]]

Uzun el, daha az kafa karıştırıcı:

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
bu aslında en mantıklı çözüm
Paweł

2
Bunu en çok, açıklamalar ve her şeyle seviyorum ve aynı zamanda gerçek bir POJO örneği de içeriyor. Harika Cevaplar, daha fazla oyu hak ediyor! Her şeyin anlaşılmasını çok daha kolay hale getiriyor!
Tigerrrrr

15

Nesne içinde dolaşırken bir dizi anahtar oluşturabilirsiniz.

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

Ardından, tuşlardan rastgele bir öğe seçin:

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

13
Object.keys burada kullanışlıdırvar keys = Object.keys(obj)
whadar

Dang << Math.floor () kullanmaktan çok daha zariftir, muhtemelen daha ucuzdur. Gerçekten aşağı inip bu bitsel operatörleri nasıl kullanacağımı öğrenmem gerekiyor.
Paul J

5
Bu durumda, bitsel operatörün kullanımı büyük olasılıkla bir hack'tir, çünkü bir girdi olarak bir tamsayıya ihtiyaç duyar, sayıyı dönüştürür. << 0Bir tam sayıya başvurmak hiçbir şey yapmaz. parseInt()aynı işi yapacak. Yani burada daha az anlaşılır kod yazmak dışında öğrenecek hiçbir şey yok.
landunder

13

Kitaplıkları kullanma yeteneğiniz varsa, Lo-Dash JS kitaplığının bu tür durumlar için çok sayıda çok yararlı yöntemi olduğunu görebilirsiniz. Bu durumda, devam edin ve kontrol edin_.sample() .

(Lo-Dash kuralı, kitaplık nesnesini _ adlandırmaktır. Projeniz için ayarlamak için aynı sayfada kurulumu kontrol etmeyi unutmayın.)

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

Sizin durumunuzda, devam edin ve şunu kullanın:

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

3

Eğer kullanıyorsanız underscore.js yapabileceğiniz:

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

Ekstra:

Birden fazla rastgele özelliğe ihtiyacınız varsa bir sayı ekleyin:

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

Yalnızca bu rastgele özelliklere sahip yeni bir nesneye ihtiyacınız varsa:

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

0

Bunu yapmanın başka bir basit yolu, işlevi uygulayan bir işlevi tanımlamaktır Math.random().

Bu işlev, 'min' ile değişen rastgele bir tamsayı döndürür.

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

Ardından, yukarıdaki işlevi parametre olarak her sağladığınızda Javascript nesnenizden bir 'anahtar' veya bir 'değer' veya 'her ikisini' çıkarın.

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] mi demek istediniz?
Bemmu

Endeks ben oluşturulan saklamak için kullanılan olduğunuz değişken rasgele sayı sadece bir kap, özel bir şey. Üretilen sayıyı başka bir değişkene kaydetmemiş olsaydım, işlevin her bir örneği getRandomArbitraryher çağrıldığında yeni bir rastgele sayı üretirdi.
Sushant Chaudhary

0

Bir JSON nesnesine şunu yerleştirmelisiniz:

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;
  }
}

Bu işlev, rastgele bir özelliğin içini döndürür.


0

Bir JavaScript nesnesinden rastgele bir özellik seçmek için aşağıdaki kodu kullanabilirsiniz:

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

Bu kod soruyu yanıtlayabilirken, sorunun nasıl ve / veya neden çözüldüğüne ilişkin ek bağlam sağlamak, yanıtlayanın uzun vadeli değerini artıracaktır.
Nic3500
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.