Выбрать случайное свойство из объекта Javascript


89

Предположим, у вас есть объект Javascript, например {'cat': 'meow', 'dog': 'woof' ...} Есть ли более лаконичный способ выбрать случайное свойство из объекта, чем этот длинный многословный способ, который я придумал :

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

Обратите внимание, что вопрос и ответы на самом деле ищут возвращение значения случайного свойства объекта, а не случайного свойства, как следует из названия вопроса.
— Контур

Ответы:


182

Выбранный ответ подойдет. Однако этот ответ будет работать быстрее:

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

3
это лучше, так как в нем не используется петля
— Доминик

14
Я провел некоторое тестирование, и оказалось, что выбранный ответ работает нормально и что выбор свойства является беспристрастным (вопреки предположениям среди ответов); однако я тестировал объект с 170 000 ключей, и решение здесь было примерно в два раза быстрее, чем выбранное решение.
— Dragonfly

8
<< 0 (сдвиг влево на 0) сокращенный метод записи Math.round ()?
— SystemicPlural

4
Этот jsperf jsperf.com/random-object-property-selection сравнивает этот ответ и выбранный ответ. Этот ответ работает в 3 раза лучше для небольших объектов (100 свойств). Для больших объектов (100k свойств) разница уменьшается в 2 раза лучше.
— Constablebrew

2
@MuhammadUmer - No. Math.random()возвращает число в диапазоне [0,1).
— Yay295

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
Кажется, это перекос в сторону первого элемента объекта. Я еще не понял почему!
— Коул Глисон

7
Это никогда не выберет первое свойство (Math.random всегда <1), и после этого у каждого числа будет 0,5 шанса быть выбранным. Итак, 0,5 для второго свойства, 0,25 для 3-го, 0,125 для 4-го и т. Д.
— SystemicPlural

4
Некоторые исправления: Эта функция может выбирать первое свойство. На первой итерации приращение префикса по счетчику приводит к тому, что правая часть уравнения оценивается как 1/1 == 1. Поскольку Math.random всегда находится в диапазоне [0,1) (от нуля до единицы, за исключением единицы), выражение истинно, и выбирается первое свойство. Что касается распределения случайного выбора, то оно равномерное. Для одного свойства есть 100% шанс, что он будет выбран. С двумя шансами 50% будет выбран любой из них. С тремя 33,3%. И так далее. Это решение требует минимального объема памяти.
— Constablebrew

3
@davidhadas Рассмотрим последовательность из трех элементов. Первый выбирается с вероятностью 1. Однако он может быть заменен (обратите внимание, что мы не возвращаемся немедленно!) Вторым элементом с вероятностью 1/2. Второй элемент, в свою очередь, может быть заменен третьим с вероятностью 1/3. Таким образом, мы получаем P (первый) = P (первый выбранный) * P (второй не выбран) * P (третий не выбран) = 1 * 1/2 * 2/3 = 1/3; P (второй) = P (второй выбранный) * P (третий не выбран) = 1/2 * 1/3 = 1/3; P (третий) = P (третий выбранный) = 1/3.
— Мартин Торнуолл 01

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
Здесь пригодится var keys = Object.keys(obj)
— Object.keys

Dang << намного изящнее, чем использование Math.floor (), возможно, и дешевле. Мне действительно нужно спуститься и научиться использовать эти побитовые операторы.
— Paul J

5
В этом случае использование побитового оператора, скорее всего, является взломом, потому что ему нужно целое число в качестве входных данных, он преобразует число. Применение << 0к целому числу ничего не даст. parseInt()будет делать ту же работу. Так что здесь нечему учиться, кроме как писать менее понятный код.
— landunder

13

Если вы умеете использовать библиотеки, вы можете обнаружить, что библиотека Lo-Dash JS имеет множество очень полезных методов для таких случаев. В этом случае продолжайте и проверяйте _.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 02

Индекс переменной , которую я использовал для хранения сгенерированного случайного числа просто контейнер, ничего особенного. Если бы я не сохранил сгенерированное число в другой переменной, тогда каждый экземпляр функции getRandomArbitraryгенерировал бы новое случайное число при каждом вызове.
— Sushant Chaudhary 02

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 05
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.