How can I get random displayed images and background colours to match - javascript

Im trying to randomly change the background colour between 4 different colours on each page visit but i also want the image that displayed on the page to match the background
For example, Red background with red.jpg, or Blue background with blue.jpg
The issue I'm having is that they are both being randomised separately and are not matching.
This is what I'm using
const imageElement = document.getElementById('random-image');
const imageSources = [ 'red.jpg', 'orange.jpg', 'yellow.jpg', 'green.jpg',];
const backgroundColors = [ 'red', 'orange', 'yellow', 'green',];
function getRandomInt(max) {
return Math.floor(Math.random() * Math.floor(max));
}
function setRandomImage() {
const randomIndex = getRandomInt(imageSources.length);
imageElement.src = imageSources[randomIndex];
}
function setRandomBackgroundColor() {
const randomIndex = getRandomInt(backgroundColors.length);
document.body.style.backgroundColor = backgroundColors[randomIndex];
}
setRandomImage();
setRandomBackgroundColor();

Original Solution
There are definitely other ways of doing this (such as using an array of objects for the background and color), but based on the code provided, here is a simple way of combining the two functions to use the same randomIndex value.
const imageElement = document.getElementById('random-image');
const imageSources = [ 'red.jpg', 'orange.jpg', 'yellow.jpg', 'green.jpg',];
const backgroundColors = [ 'red', 'orange', 'yellow', 'green',];
function getRandomInt(max) {
return Math.floor(Math.random() * Math.floor(max));
}
function setRandomImageAndBackground() {
const randomIndex = getRandomInt(imageSources.length);
imageElement.src = imageSources[randomIndex];
document.body.style.backgroundColor = backgroundColors[randomIndex];
}
setRandomImageAndBackground();
Alternative Solution
Another way to use only one randomIndex value is to declare the randomIndex outside of any functions. Because the index seems to only need to be declared once when the page loads, this should work just fine for your use-case.
You could still combine both functions using this method, but declaring the randomIndex outside of any functions allows you to use that value anywhere as it becomes a global variable. So if for some reason you need the functions to be separate, this would allow you to do that.
const imageElement = document.getElementById('random-image');
const imageSources = [ 'red.jpg', 'orange.jpg', 'yellow.jpg', 'green.jpg',];
const backgroundColors = [ 'red', 'orange', 'yellow', 'green',];
const randomIndex = getRandomInt(imageSources.length);
function getRandomInt(max) {
return Math.floor(Math.random() * Math.floor(max));
}
function setRandomImage() {
imageElement.src = imageSources[randomIndex];
}
function setRandomBackgroundColor() {
document.body.style.backgroundColor = backgroundColors[randomIndex];
}
setRandomImage();
setRandomBackgroundColor();
Object-based Solution
Both the above solutions use two separate arrays for the images and colors, which works fine as long as you make sure both arrays are the same length. Sometimes that can be difficult to maintain depending on how many items are in these arrays and so I prefer to use arrays of objects when dealing with multiple arrays that are meant to be linked/related.
const imageElement = document.getElementById('random-image'),
imagesAndColors = [
{ img: 'red.jpg', background: 'red' },
{ img: 'orange.jpg', background: 'orange' },
{ img: 'yellow.jpg', background: 'yellow' },
{ img: 'green.jpg', background: 'green' },
]
function getRandomInt(max) {
return Math.floor(Math.random() * Math.floor(max));
}
function setRandomImageAndBackground() {
const randomIndex = getRandomInt(imagesAndColors.length)
imageElement.src = imagesAndColors[randomIndex].img
document.body.style.backgroundColor = imagesAndColors[randomIndex].background
}
setRandomImageAndBackground()
This is similar to the original idea of combining the two functions, however the main idea is that adding/removing images and background colors from your array will be easier.

Related

compare order of two arrays

Say I have this default array in JavaScript:
const default = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet']
I have this array provided by the user:
const user_arr = ['red', 'green', 'violet']
I need to compare these two arrays and validate that the user array is in the correct order (i.e. I am allowed to skip levels, but reverse order is not allowed).
So the following arrays would be valid:
['red', 'orange', 'violet']
['yellow', 'blue']
['green', 'indigo', 'violet']
There arrays would be invalid:
['red', 'violet', 'orange']
['green', 'violet', 'yellow]
Is this possible without using complex tree data structures?
Here I map each element in the user array to its index in the proper array.
The array of indexes is checked to make sure it's in ascending order.
note that "default" is a javascript keyword and isn't a valid variable name
const proper = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet']
const isValid = (arr) => {
const isAscending = (arr) => arr.every((el, i, a) =>
i === a.length - 1
? true
: el < a[i + 1]
);
return isAscending(arr.map(el => proper.indexOf(el)));
}
const user_arr = ['red', 'green', 'blue']
console.log(isValid(user_arr));
console.log(isValid(['red', 'indigo', 'orange']));
I don't know if it is the most efficient way, but this should work:
/**
*
* #param {string[]} ref
* #param {string[]} array
* #return {boolean}
*/
function checkValidity(ref, array) {
let prev = 0;
for (let i = 0; i < array.length; i++) {
const current = ref.findIndex((elt) => elt === array[i]);
if (current >= prev) prev = current;
else return false;
}
return true;
}
This approach uses a Map which maps the value of an item to its index within the array.
Using that map we then we check for every element in a user supplied array whether we have that item in our original array. If we have not, the user array is invalid. If it is a known item we need to get its position in the original array and check if it greater than the previous position we have checked. If it is, everything is fine, if it is not, the user array is invalid.
Remarks on solution
This solution does not allow for duplicate values as it checks for <, not <=. If you have duplicate values in your original array the latest of all occurrences of that duplicate value will determine its position in the array. Currently this implementation does not accept empty arrays but one could easily change that so an empty array would be accepted.
Complexity
The advantage of using a Map is the speedup for the lookup of the index which can be done in O(1). Therefore, one needs O(n) time with n being the number of items in the original array once to initialize the Map. Then one can use that Map to check whether a user array is valid in worst case O(m) time (e.g. for a valid array) where m is the number of items in a user supplied array. Using just arrays and methods like indexOf() or find() will have a worst case time complexity of O(m * n). For small arrays such as yours those things won't really matter though.
const order = ["red", "orange", "yellow", "green", "blue", "indigo", "violet"];
const indexToValue = new Map();
order.forEach((item, idx) => indexToValue.set(item, idx));
const validArrays = [
["red"],
["red", "orange", "violet"],
["yellow", "blue"],
["green", "indigo", "violet"],
];
const invalidArrays = [
["red", "violet", "orange"],
["green", "violet", "yellow"],
];
/**
*
* #param {Array<string>} userArray
* #param {Map<string, number>} indexToValue
* #returns
*/
function checkCorrectness(userArray, indexToValue) {
if (!Array.isArray(userArray) || userArray.length === 0) return false;
let prev = -1;
return userArray.every((item) => {
// an unknown item is in the user array so it is invalid
if (!indexToValue.has(item)) return false;
// get index of the element in the original array
const idxInOrig = indexToValue.get(item);
// if the current index is smaller than the previous index -> invalid! stop immediately
if (idxInOrig < prev) return false;
// everything is fine current index is bigger than previous -> continue with next one
prev = idxInOrig;
return true;
});
}
console.log("Invalid arrays")
invalidArrays.forEach(invalid => console.log(checkCorrectness(invalid, indexToValue)));
console.log("Valid arrays")
validArrays.forEach(valid => console.log(checkCorrectness(valid, indexToValue)));

How to remove an element from an array after it's called only once?

When a random element is called from the videos array, it should be deleted without the index being empty and undefined afterwards. The problem is that splice_video(); keeps calling the same element twice, when it's supposed to delete the element from the array after being called only once. (Each element in the array is a function).
function playNextVideo() {
const videos = [showVideo1,showVideo2,showVideo3,showVideo4,showVideo5];
const random_video = Math.floor(Math.random() * videos.length);
const video = videos.splice(random_video, 1);
const splice_video = video[0]();
splice_video();
}
Declare the array of functions outside, not inside, so that the removal of the function from the array is persistent.
const videoFns = [showVideo1, showVideo2, showVideo3, showVideo4, showVideo5];
function playNextVideo() {
const randomIndex = Math.floor(Math.random() * videoFns.length);
const [videoFn] = videoFns.splice(randomIndex, 1);
videoFn();
}
Live demo:
const videoFns = Array.from(
{ length: 5 },
(_, i) => () => console.log('video ' + i)
);
function playNextVideo() {
if (!videoFns.length) return;
const randomIndex = Math.floor(Math.random() * videoFns.length);
const [videoFn] = videoFns.splice(randomIndex, 1);
videoFn();
}
document.querySelector('button').addEventListener('click', playNextVideo);
<button>click</button>

Getting an array item [duplicate]

Consider:
var myArray = ['January', 'February', 'March'];
How can I select a random value from this array using JavaScript?
It's a simple one-liner:
const randomElement = array[Math.floor(Math.random() * array.length)];
For example:
const months = ["January", "February", "March", "April", "May", "June", "July"];
const random = Math.floor(Math.random() * months.length);
console.log(random, months[random]);
If you've already got underscore or lodash included in your project you can use _.sample.
// will return one item randomly from the array
_.sample(['January', 'February', 'March']);
If you need to get more than one item randomly, you can pass that as a second argument in underscore:
// will return two items randomly from the array using underscore
_.sample(['January', 'February', 'March'], 2);
or use the _.sampleSize method in lodash:
// will return two items randomly from the array using lodash
_.sampleSize(['January', 'February', 'March'], 2);
You may consider defining a function on the Array prototype, in order to create a method [].sample() which returns a random element.
First, to define the prototype function, place this snippet in your code:
Array.prototype.sample = function(){
return this[Math.floor(Math.random()*this.length)];
}
Later, to sample a random element from the array, just call .sample():
[1,2,3,4].sample() //=> a random element
I'm releasing these code snippets into the public domain, under the terms of the CC0 1.0 license.
~~ is much faster than Math.Floor(), so when it comes to performance optimization while producing output using UI elements, ~~ wins the game. MORE INFO
var rand = myArray[~~(Math.random() * myArray.length)];
But if you know that the array is going to have millions of elements then you might want to reconsider between Bitwise Operator and Math.Floor(), as bitwise operators behave weirdly with large numbers. See below example explained with the output.
var number = Math.floor(14444323231.2); // => 14444323231
var number = 14444323231.2 | 0; // => 1559421343
The shortest version:
var myArray = ['January', 'February', 'March'];
var rand = myArray[(Math.random() * myArray.length) | 0]
console.log(rand)
Say you want to choose a random item that is different from the last time (not really random, but still a common requirement)...
/**
* Return a random element from an array that is
* different than `last` (as long as the array has > 1 items).
* Return null if the array is empty.
*/
function getRandomDifferent(arr, last = undefined) {
if (arr.length === 0) {
return null;
} else if (arr.length === 1) {
return arr[0];
} else {
let num = 0;
do {
num = Math.floor(Math.random() * arr.length);
} while (arr[num] === last);
return arr[num];
}
}
Implement like this:
const arr = [1,2,3];
const r1 = getRandomDifferent(arr);
const r2 = getRandomDifferent(arr, r1); // r2 is different than r1.
If you have fixed values (like a month name list) and want a one-line solution
var result = ['January', 'February', 'March'][Math.floor(Math.random() * 3)]
The second part of the array is an access operation as described in Why does [5,6,8,7][1,2] = 8 in JavaScript?
If you want to write it on one line, like Pascual's solution, another solution would be to write it using ES6's find function (based on the fact, that the probability of randomly selecting one out of n items is 1/n):
var item = ['A', 'B', 'C', 'D'].find((_, i, ar) => Math.random() < 1 / (ar.length - i));
console.log(item);
Use that approach for testing purposes and if there is a good reason to not save the array in a seperate variable only. Otherwise the other answers (floor(random()*length and using a seperate function) are your way to go.
Faker.js has many utility functions for generating random test data. It is a good option in the context of a test suite:
const faker = require('faker');
faker.helpers.arrayElement(['January', 'February', 'March']);
As commenters have mentioned, you generally should not use this library in production code.
Editing Array prototype can be harmful. Here it is a simple function to do the job.
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
}
Usage:
// Example 1
var item = getArrayRandomElement(['January', 'February', 'March']);
// Example 2
var myArray = ['January', 'February', 'March'];
var item = getArrayRandomElement(myArray);
If you need to fetch a random item more than once, then, obviously you would use a function. One way is to make that function a method of the Array.prototype, but that will normally get you shouted down for tampering with built in prototypes.
However, you can add the method to the specific array itself:
var months = ['January', 'February', 'March'];
months.random = function() {
return this[Math.floor(Math.random()*this.length)];
};
That way you can use months.random() as often as you like without interfering with the generic Array.prototype.
As with any random function, you run the risk of getting the same value successively. If you don’t want that, you will need to track the previous value with another property:
months.random=function() {
var random;
while((random=this[Math.floor(Math.random()*this.length)]) == this.previous);
this.previous=random;
return random;
};
If you’re going to do this sort of thing often, and you don’t want to tamper with Array.prototype, you can do something like this:
function randomValue() {
return this[Math.floor(Math.random()*this.length)];
}
var data = [ … ];
var moreData = [ … ];
data.random=randomValue;
moreData.random=randomValue;
Many of the offered solutions add a method to a specific Array which restricts it's use to just that array. This solution is reusable code that works for any array and can be made type safe.
TypeScript
export function randChoice<T>(arr: Array<T>): T {
return arr[Math.floor(Math.random() * arr.length)]
}
JavaScript
export function randChoice(arr) {
return arr[Math.floor(Math.random() * arr.length)]
}
To get crypto-strong random item form array use
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) )
Recursive, standalone function which can return any number of items (identical to 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])
}
This is similar to, but more general than, #Jacob Relkin's solution:
This is ES2015:
const randomChoice = arr => {
const randIndex = Math.floor(Math.random() * arr.length);
return arr[randIndex];
};
The code works by selecting a random number between 0 and the length of the array, then returning the item at that index.
var item = myArray[Math.floor(Math.random()*myArray.length)];
or equivalent shorter version:
var item = myArray[(Math.random()*myArray.length)|0];
Sample code:
var myArray = ['January', 'February', 'March'];
var item = myArray[(Math.random()*myArray.length)|0];
console.log('item:', item);
Simple Function :
var myArray = ['January', 'February', 'March'];
function random(array) {
return array[Math.floor(Math.random() * array.length)]
}
random(myArray);
OR
var myArray = ['January', 'February', 'March'];
function random() {
return myArray[Math.floor(Math.random() * myArray.length)]
}
random();
OR
var myArray = ['January', 'February', 'March'];
function random() {
return myArray[Math.floor(Math.random() * myArray.length)]
}
random();
In my opinion, better than messing around with prototypes , or declaring it just in time, I prefer exposing it to window:
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)];
}
Now anywhere on your app you call it like:
var rand = window.choice.call(array)
This way you can still use for(x in array) loop properly
I've found a way around the top answer's complications, just by concatenating the variable rand to another variable that allows that number to be displayed inside the calling of myArray[];. By deleting the new array created and toying around with it's complications, I've come up with a working solution:
<!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>
static generateMonth() {
const theDate = ['January', 'February', 'March'];
const randomNumber = Math.floor(Math.random()*3);
return theDate[randomNumber];
};
You set a constant variable to the array, you then have another constant that chooses randomly between the three objects in the array and then the function simply returns the results.
Looking for a true one-liner I came to this:
['January', 'February', 'March'].reduce((a, c, i, o) => { return o[Math.floor(Math.random() * Math.floor(o.length))]; })
By adding a method on prototype of array you can get random values easly.
In this example you can get single or multiple random values from array.
You can run to test code by clicking snippet button.
Array.prototype.random = function(n){
if(n&&n>1){
const a = [];
for(let i = 0;i<n;i++){
a.push(this[Math.floor(Math.random()*this.length)]);
}
return a;
} else {
return this[Math.floor(Math.random()*this.length)];
}
}
const mySampleArray = ['a','b','c','d','e','f','g','h'];
mySampleArray.random(); // return any random value etc. 'a', 'b'
mySampleArray.random(3); //retun an array with random values etc: ['b','f','a'] , ['d','b','d']
alert(mySampleArray.random());
alert(mySampleArray.random(3));
Method 1:
Use Math.random() function to get the random number between(0-1, 1
exclusive).
Multiply it by the array length to get the numbers
between(0-arrayLength).
Use Math.floor() to get the index ranging
from(0 to arrayLength-1).
const arr = ["foo","bar"];
const randomlyPickedString=arr[Math.floor(Math.random() * arr.length)];
console.log(randomlyPickedString);
Method 2:
The random(a, b) method is used to generates a number between(a to b, b exclusive).
Taking the floor value to range the numbers from (1 to arrayLength).
Subtract 1 to get the index ranging from(0 to arrayLength-1).
const arr = ["foo","bar"];
const randomlyPickedString=arr[Math.floor(random(1, 5))-1];
console.log(randomlyPickedString);
A generic way to get random element(s):
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;
}
Here is an example of how to do it:
$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)];
Create one random value and pass to array
Please try following code..
//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);
randojs makes this a little more simple and readable:
console.log( rando(['January', 'February', 'March']).value );
<script src="https://randojs.com/1.0.0.js"></script>
I am really surprised nobody tried to use native random values:
array[Date.now()%array.length]
It will not work for array length over 160000000000, but I am sure you will never create arrays like this
UPD
As far as you question is how to pick random value from array called myArray (with len=3), the solution should be:
myArray[Date.now()%myArray.length]

How do I get elements from an array without repetition?

How do I get 5 elements from an array without repetition?
I'm trying to create an online version of story dice using Tumult Hype. All that I need to do is choose 5 image names from an array without repetition. But I just can't get it to work.
I've tried borrowing code from other stackoverflow answers and I can't get them working.
The code below is currently working but gives me repeats. How do I tinker with it to eliminate the repeats?
(You can see it in action here: https://davebirss.com/storydice/)
I know that it's probably verbose and inelegant. I only speak pidgin javascript, I'm afraid. And what I'm trying to do is currently beyond my ability.
Thank you so much in advance for your help.
var diceRoll = ['${resourcesFolderName}/story_dice1.png',
'${resourcesFolderName}/story_dice2.png',
'${resourcesFolderName}/story_dice3.png',
...,
'${resourcesFolderName}/story_dice51.png']
function choose(n, arr) {
while (arr.length > n) {
var del = Math.floor(Math.random() * arr.length);
arr = arr.filter(function(item, i) {
return i !== del;
});
}
return arr;}
var result1 = [choose(1, diceRoll)];
var result2 = [choose(1, diceRoll)];
var result3 = [choose(1, diceRoll)];
var result4 = [choose(1, diceRoll)];
var result5 = [choose(1, diceRoll)];
hypeDocument.getElementById("dice1").innerHTML = "<img src='"+result1+" 'height='125' width='125'>";
hypeDocument.getElementById("dice2").innerHTML = "<img src='"+result2+" 'height='125' width='125'>";
hypeDocument.getElementById("dice3").innerHTML = "<img src='"+result3+" 'height='125' width='125'>";
hypeDocument.getElementById("dice4").innerHTML = "<img src='"+result4+" 'height='125' width='125'>";
hypeDocument.getElementById("dice5").innerHTML = "<img src='"+result5+" 'height='125' width='125'>";
Update
Thank you all for your help. I'm sure all the answers were great but the snippet from U25lYWt5IEJhc3RhcmQg is the code that I managed to successfully incorporate. For the record, this is how I did it:
const rollTheDice = (arr, n) => {
const randomN = [];
while(randomN.length < n){
const randomIndex = Math.floor(Math.random()*arr.length);
randomN.push(arr[randomIndex]);
arr.splice(randomIndex, 1);
}
return randomN;}
var result1 = (rollTheDice(images,1));
var result2 = (rollTheDice(images,1));
var result3 = (rollTheDice(images,1));
var result4 = (rollTheDice(images,1));
var result5 = (rollTheDice(images,1));
I've been repeatedly reloading the page and haven't seen any repeats yet. Perfect!
You could take an array of indices and check if the index exist, then get a new index or push this index.
var length = 51, // your count of items
indices = [], // the result set with indices
count = 5, // the amount of wanted indices
random; // guess what?
while (indices.length < count) { // check length
random = Math.floor(Math.random() * length); // get random value
if (indices.includes(random)) continue; // continue if already selected
indices.push(random); // if not take it
}
console.log(indices);
I guess, the trickiest part here is not to waste the performance, limiting possible options to those, not previously chosen:
const images = ['a','b','c','d','e','f'];
const rollTheDice = (arr, n) => {
const randomN = [];
while(randomN.length < n){
const randomIndex = Math.floor(Math.random()*arr.length);
randomN.push(arr[randomIndex]);
arr.splice(randomIndex, 1);
}
return randomN;
}
console.log(rollTheDice(images, 5));
Make a copy of diceRoll array (diceRollCopy).
Use the new array(diceRollCopy) as argument of choose method.
Whenever you get a
result using choose method remove that result from the Copy array
(diceRollCopy).
You would need to reset the diceRollCopy to diceRoll
after each set of results have been accessed.
Copy it, then shuffle the copy, and remove the first element from the array each time:
const copy = [...diceRoll].sort(e => 0.5 - Math.random());
And in your choosing function:
const chosen = copy.shift();
You want a random permutation which all elements is uniq and from one dataset, here is my implementation:
var array = [1, 2, 3, 4, 5, 6];
/**
* uniqGet
* #param {*} array source array
* #param {*} num how many elements to get
*/
function uniqGet(array, num) {
if (array.length < num) {
throw new Error("num should less than options");
}
let res = [];
while (num > 0) {
let index = Math.floor(Math.random() * array.length);
res.push(array[index]);
array.splice(index, 1);
num--;
}
return res;
}
let result = uniqGet(array, 3); // [x, y, z]

Trying to get only one value out of an array [duplicate]

Consider:
var myArray = ['January', 'February', 'March'];
How can I select a random value from this array using JavaScript?
It's a simple one-liner:
const randomElement = array[Math.floor(Math.random() * array.length)];
For example:
const months = ["January", "February", "March", "April", "May", "June", "July"];
const random = Math.floor(Math.random() * months.length);
console.log(random, months[random]);
If you've already got underscore or lodash included in your project you can use _.sample.
// will return one item randomly from the array
_.sample(['January', 'February', 'March']);
If you need to get more than one item randomly, you can pass that as a second argument in underscore:
// will return two items randomly from the array using underscore
_.sample(['January', 'February', 'March'], 2);
or use the _.sampleSize method in lodash:
// will return two items randomly from the array using lodash
_.sampleSize(['January', 'February', 'March'], 2);
You may consider defining a function on the Array prototype, in order to create a method [].sample() which returns a random element.
First, to define the prototype function, place this snippet in your code:
Array.prototype.sample = function(){
return this[Math.floor(Math.random()*this.length)];
}
Later, to sample a random element from the array, just call .sample():
[1,2,3,4].sample() //=> a random element
I'm releasing these code snippets into the public domain, under the terms of the CC0 1.0 license.
~~ is much faster than Math.Floor(), so when it comes to performance optimization while producing output using UI elements, ~~ wins the game. MORE INFO
var rand = myArray[~~(Math.random() * myArray.length)];
But if you know that the array is going to have millions of elements then you might want to reconsider between Bitwise Operator and Math.Floor(), as bitwise operators behave weirdly with large numbers. See below example explained with the output.
var number = Math.floor(14444323231.2); // => 14444323231
var number = 14444323231.2 | 0; // => 1559421343
The shortest version:
var myArray = ['January', 'February', 'March'];
var rand = myArray[(Math.random() * myArray.length) | 0]
console.log(rand)
Say you want to choose a random item that is different from the last time (not really random, but still a common requirement)...
/**
* Return a random element from an array that is
* different than `last` (as long as the array has > 1 items).
* Return null if the array is empty.
*/
function getRandomDifferent(arr, last = undefined) {
if (arr.length === 0) {
return null;
} else if (arr.length === 1) {
return arr[0];
} else {
let num = 0;
do {
num = Math.floor(Math.random() * arr.length);
} while (arr[num] === last);
return arr[num];
}
}
Implement like this:
const arr = [1,2,3];
const r1 = getRandomDifferent(arr);
const r2 = getRandomDifferent(arr, r1); // r2 is different than r1.
If you have fixed values (like a month name list) and want a one-line solution
var result = ['January', 'February', 'March'][Math.floor(Math.random() * 3)]
The second part of the array is an access operation as described in Why does [5,6,8,7][1,2] = 8 in JavaScript?
If you want to write it on one line, like Pascual's solution, another solution would be to write it using ES6's find function (based on the fact, that the probability of randomly selecting one out of n items is 1/n):
var item = ['A', 'B', 'C', 'D'].find((_, i, ar) => Math.random() < 1 / (ar.length - i));
console.log(item);
Use that approach for testing purposes and if there is a good reason to not save the array in a seperate variable only. Otherwise the other answers (floor(random()*length and using a seperate function) are your way to go.
Faker.js has many utility functions for generating random test data. It is a good option in the context of a test suite:
const faker = require('faker');
faker.helpers.arrayElement(['January', 'February', 'March']);
As commenters have mentioned, you generally should not use this library in production code.
Editing Array prototype can be harmful. Here it is a simple function to do the job.
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
}
Usage:
// Example 1
var item = getArrayRandomElement(['January', 'February', 'March']);
// Example 2
var myArray = ['January', 'February', 'March'];
var item = getArrayRandomElement(myArray);
If you need to fetch a random item more than once, then, obviously you would use a function. One way is to make that function a method of the Array.prototype, but that will normally get you shouted down for tampering with built in prototypes.
However, you can add the method to the specific array itself:
var months = ['January', 'February', 'March'];
months.random = function() {
return this[Math.floor(Math.random()*this.length)];
};
That way you can use months.random() as often as you like without interfering with the generic Array.prototype.
As with any random function, you run the risk of getting the same value successively. If you don’t want that, you will need to track the previous value with another property:
months.random=function() {
var random;
while((random=this[Math.floor(Math.random()*this.length)]) == this.previous);
this.previous=random;
return random;
};
If you’re going to do this sort of thing often, and you don’t want to tamper with Array.prototype, you can do something like this:
function randomValue() {
return this[Math.floor(Math.random()*this.length)];
}
var data = [ … ];
var moreData = [ … ];
data.random=randomValue;
moreData.random=randomValue;
Many of the offered solutions add a method to a specific Array which restricts it's use to just that array. This solution is reusable code that works for any array and can be made type safe.
TypeScript
export function randChoice<T>(arr: Array<T>): T {
return arr[Math.floor(Math.random() * arr.length)]
}
JavaScript
export function randChoice(arr) {
return arr[Math.floor(Math.random() * arr.length)]
}
To get crypto-strong random item form array use
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) )
Recursive, standalone function which can return any number of items (identical to 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])
}
This is similar to, but more general than, #Jacob Relkin's solution:
This is ES2015:
const randomChoice = arr => {
const randIndex = Math.floor(Math.random() * arr.length);
return arr[randIndex];
};
The code works by selecting a random number between 0 and the length of the array, then returning the item at that index.
var item = myArray[Math.floor(Math.random()*myArray.length)];
or equivalent shorter version:
var item = myArray[(Math.random()*myArray.length)|0];
Sample code:
var myArray = ['January', 'February', 'March'];
var item = myArray[(Math.random()*myArray.length)|0];
console.log('item:', item);
Simple Function :
var myArray = ['January', 'February', 'March'];
function random(array) {
return array[Math.floor(Math.random() * array.length)]
}
random(myArray);
OR
var myArray = ['January', 'February', 'March'];
function random() {
return myArray[Math.floor(Math.random() * myArray.length)]
}
random();
OR
var myArray = ['January', 'February', 'March'];
function random() {
return myArray[Math.floor(Math.random() * myArray.length)]
}
random();
In my opinion, better than messing around with prototypes , or declaring it just in time, I prefer exposing it to window:
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)];
}
Now anywhere on your app you call it like:
var rand = window.choice.call(array)
This way you can still use for(x in array) loop properly
I've found a way around the top answer's complications, just by concatenating the variable rand to another variable that allows that number to be displayed inside the calling of myArray[];. By deleting the new array created and toying around with it's complications, I've come up with a working solution:
<!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>
static generateMonth() {
const theDate = ['January', 'February', 'March'];
const randomNumber = Math.floor(Math.random()*3);
return theDate[randomNumber];
};
You set a constant variable to the array, you then have another constant that chooses randomly between the three objects in the array and then the function simply returns the results.
Looking for a true one-liner I came to this:
['January', 'February', 'March'].reduce((a, c, i, o) => { return o[Math.floor(Math.random() * Math.floor(o.length))]; })
By adding a method on prototype of array you can get random values easly.
In this example you can get single or multiple random values from array.
You can run to test code by clicking snippet button.
Array.prototype.random = function(n){
if(n&&n>1){
const a = [];
for(let i = 0;i<n;i++){
a.push(this[Math.floor(Math.random()*this.length)]);
}
return a;
} else {
return this[Math.floor(Math.random()*this.length)];
}
}
const mySampleArray = ['a','b','c','d','e','f','g','h'];
mySampleArray.random(); // return any random value etc. 'a', 'b'
mySampleArray.random(3); //retun an array with random values etc: ['b','f','a'] , ['d','b','d']
alert(mySampleArray.random());
alert(mySampleArray.random(3));
Method 1:
Use Math.random() function to get the random number between(0-1, 1
exclusive).
Multiply it by the array length to get the numbers
between(0-arrayLength).
Use Math.floor() to get the index ranging
from(0 to arrayLength-1).
const arr = ["foo","bar"];
const randomlyPickedString=arr[Math.floor(Math.random() * arr.length)];
console.log(randomlyPickedString);
Method 2:
The random(a, b) method is used to generates a number between(a to b, b exclusive).
Taking the floor value to range the numbers from (1 to arrayLength).
Subtract 1 to get the index ranging from(0 to arrayLength-1).
const arr = ["foo","bar"];
const randomlyPickedString=arr[Math.floor(random(1, 5))-1];
console.log(randomlyPickedString);
A generic way to get random element(s):
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;
}
Here is an example of how to do it:
$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)];
Create one random value and pass to array
Please try following code..
//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);
randojs makes this a little more simple and readable:
console.log( rando(['January', 'February', 'March']).value );
<script src="https://randojs.com/1.0.0.js"></script>
I am really surprised nobody tried to use native random values:
array[Date.now()%array.length]
It will not work for array length over 160000000000, but I am sure you will never create arrays like this
UPD
As far as you question is how to pick random value from array called myArray (with len=3), the solution should be:
myArray[Date.now()%myArray.length]

Categories