ChatGPT解决这个技术问题 Extra ChatGPT

Get a random item from a JavaScript array [duplicate]

This question already has answers here: Getting a random value from a JavaScript array (27 answers) Closed 7 years ago.

var items = Array(523, 3452, 334, 31, ..., 5346);

How do I get random item from items?

the answer will not involve jQuery
I've never seen so many absolutely identical responses to a question...
great minds, @Blindy
I found a way to involve jQuery!! (see my second answer)
This question is absolutely identical to Getting random value from an array, yet the Mighty Mods haven't bothered to close it in 3+ years. Instead, they close "unconstructive" questions with hundreds of votes.

C
Corey
var item = items[Math.floor(Math.random()*items.length)];

Math.random() will never be 1, nor should it. The largest index should always be one less than the length, or else you'll get an undefined error.
Elegant solution. I tested it: var items = ["a","e","i","o","u"] var objResults = {} for(var i = 0; i < 1000000; i++){ var randomElement = items[Math.floor(Math.random()*items.length)] if (objResults[randomElement]){ objResults[randomElement]++ }else{ objResults[randomElement] = 1 } } console.log(objResults) The results are pretty randomized after 1000000 iterations: Object {u: 200222, o: 199543, a: 199936, e: 200183, i: 200116}
@AnkitPatial: That's a way to "scramble" an array, but the question is about getting a randomly selected element from an array. There's a big difference.
@virus Math.round is not a valid substitution for Math.floor. Using round would cause accidentally referencing an undefined index, say in the case Math.random() is 0.95 and items.length is 5. Math.round(0.95*5) is 5, which would be an invalid index. floor(random) will always be zero in your example.
Nice answer. You can be shorter: items[items.length * Math.random() | 0] :)
c
chim

Use underscore (or loDash :)):

var randomArray = [
   '#cc0000','#00cc00', '#0000cc'
];

// use _.sample
var randomElement = _.sample(randomArray);

// manually use _.random
var randomElement = randomArray[_.random(randomArray.length-1)];

Or to shuffle an entire array:

// use underscore's shuffle function
var firstRandomElement = _.shuffle(randomArray)[0];

Using underscore or lodash for just one function would be overkill, but if you're doing any complicated js functionality then it can save hours or even days.
Nowadays underscore has also better choice for this _.sample([1, 2, 3, 4, 5, 6])
You will probably be using _ on any real project. It's not a bad thing.
lodash is modularized on npm, so you can install just the sample function if you want: npmjs.com/package/lodash.sample
My creed is to use as few libraries as possible for any project. With that being said, I always end up using lodash. It's too convenient to not use
J
JUDE DAILY

1. solution: define Array prototype

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

that will work on inline arrays

[2,3,5].random()

and of course predefined arrays

var list = [2,3,5]
list.random()

2. solution: define custom function that accepts list and returns element

function get_random (list) {
  return list[Math.floor((Math.random()*list.length))];
}


get_random([2,3,5])

@EvanCarroll better reference a useful link instead of downvoting for subjective notions such as coding style which does not make the answer invalid nor "unuseful" ! stackoverflow.com/questions/14034180/…
Upvoted because downvoting for adding something to Array.prototype is not useful to anyone without explanation.
The issue with adding a new function to Array.prototype is the same issue as adding a global variable - someone/something else may be using the same "name" for something different - which can cause subtle mahem
Thank you for this. Far more usable than typing the whole vanilla formula or calling a custom function when the code requires it more than once. As for the valid concerns about conflicts, that's what namespacing is for: ns. or ns_ format where applicable.
@Schmoo I just ran into one of those "subtle mayhem" situations. I shortened the prototype's name to "rand". Then suddenly during a for (let i in arr) loop, it iterates all the expected indexes, and also iterates an index of "rand". Had to switch to a for (let i=0,l=arr.length;i<l;i++) loop to fix it.
A
Alnitak

If you really must use jQuery to solve this problem (NB: you shouldn't):

(function($) {
    $.rand = function(arg) {
        if ($.isArray(arg)) {
            return arg[$.rand(arg.length)];
        } else if (typeof arg === "number") {
            return Math.floor(Math.random() * arg);
        } else {
            return 4;  // chosen by fair dice roll
        }
    };
})(jQuery);

var items = [523, 3452, 334, 31, ..., 5346];
var item = jQuery.rand(items);

This plugin will return a random element if given an array, or a value from [0 .. n) given a number, or given anything else, a guaranteed random value!

For extra fun, the array return is generated by calling the function recursively based on the array's length :)

Working demo at http://jsfiddle.net/2eyQX/


@neoascetic the point of that line is that picking an element from an array is not a jQuery problem, it's generic JS.
@damd re: your proposed edit - it was clearly incorrect, since there's a clear split between defining the plugin in the IIFE, and using the plugin. However for consistency I have replaced the $ in the usage line with jQuery.
Definitely. There are less than an average of 3 chained methods per line, and the $ is not being used at least once per each line, therefore it does not have enough jQuery.
This is not a problem that requires jQuery.
K
K-Gun

Here's yet another way:

function rand(items) {
    // "~~" for a closest "int"
    return items[~~(items.length * Math.random())];
}

Or as recommended below by @1248177:

function rand(items) {
    // "|" for a kinda "int div"
    return items[items.length * Math.random() | 0];
}

What is that crazy ~~? Never seen that in JS before.
@hatboysam: do a search - it essentially converts the operand to the closest integer.
Actually, it rounds it down, like Math.floor.
Nice answer. You still can be shorter: items[items.length * Math.random() | 0] :)
"Actually, it rounds it down, like Math.floor" @programmer5000. It actually rounds towards 0, i.e. ~~(-1.5) evaluates to -1, not the -2 which Math.floor gives.
g
gen_Eric
var random = items[Math.floor(Math.random()*items.length)]

P
Peter Mortensen

jQuery is JavaScript! It's just a JavaScript framework. So to find a random item, just use plain old JavaScript, for example,

var randomItem = items[Math.floor(Math.random()*items.length)]

I
Ivan Pirog
// 1. Random shuffle items
items.sort(function() {return 0.5 - Math.random()})

// 2. Get first item
var item = items[0]

Shorter:

var item = items.sort(function() {return 0.5 - Math.random()})[0];

Even shoter (by José dB.):

let item = items.sort(() => 0.5 - Math.random())[0];

items[1] is the second item, the first is items[0].
Oh, sorry. Of coz items[0]
This does not give you a uniform shuffle: sroucheray.org/blog/2009/11/…
Next shoter: let item = items.sort(() => 0.5 - Math.random())[0];
Would be also good to know the complexity of thar algorithm :)
B
Blindy
var rndval=items[Math.floor(Math.random()*items.length)];

M
Martijn Pieters
var items = Array(523,3452,334,31,...5346);

function rand(min, max) {
  var offset = min;
  var range = (max - min) + 1;

  var randomNumber = Math.floor( Math.random() * range) + offset;
  return randomNumber;
}


randomNumber = rand(0, items.length - 1);

randomItem = items[randomNumber];

credit:

Javascript Function: Random Number Generator


FYI, this could be one lined: Math.floor(Math.random() * (max - min + 1)) + min
A
Aayan L

If you are using node.js, you can use unique-random-array. It simply picks something random from an array.


P
Peter Mortensen

An alternate way would be to add a method to the Array prototype:

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

 var teams = ['patriots', 'colts', 'jets', 'texans', 'ravens', 'broncos']
 var chosen_team = teams.random(teams.length)
 alert(chosen_team)

arrays have a built-in length property - why pass it as a parameter?!
i guess my point is that you can pass in any length you want not just the length of the array - if you just wanted to randomize the first two entries you could put length as 2 without changing the method. I don't think there is a performance issue with passing the length property as a parameter but i may be wrong
It is generally not a good idea to extend host objects like this. You risk tripping over a future implementation of Array.random by the client that behaves differently than yours, breaking future code. You could at least check to make sure it doesn't exist before adding it.
N
Nicolas
const ArrayRandomModule = {
  // get random item from array
  random: function (array) {
    return array[Math.random() * array.length | 0];
  },

  // [mutate]: extract from given array a random item
  pick: function (array, i) {
    return array.splice(i >= 0 ? i : Math.random() * array.length | 0, 1)[0];
  },

  // [mutate]: shuffle the given array
  shuffle: function (array) {
    for (var i = array.length; i > 0; --i)
      array.push(array.splice(Math.random() * i | 0, 1)[0]);
    return array;
  }
}

Pointed out in many comments, this is a bad practice, please refer to stackoverflow.com/questions/14034180/… :)
I just change the declaration to avoid showing bad pactice method declaration