how to choose a random item from arrays nested in an object - javascript

I'm trying a project that will choose a random answer out of one of the 3 nested arrays in my object. My goal is to know afterwards out of which array the answer came, so I can use that to know what the new sentence will be.
The example below works with 1 array, but i want to know if the answer is a good, bad or doubt answer, hence why i put it in an object.
EDIT: code below gives me a random property in my object, but i need to go one step deeper. The comment next to it is what i tried but it gives me undefined.
const randomAnswers = {
goodAnswers: ['yes','Absolutely','certainly',"I'm sure",'HELL YES'],
maybes: ['maybe','probably','perhaps',"honestly man, i really don't
know this one"],
badAnswers: ['LOL NO','no way man','maybe',"forget it",'HELL no','Are
you serious?']
};
{
const init = () => {
console.log("initiated");
let answer = document.querySelector('.answer');
answer.style.opacity = 0;
setTimeout(fixSentence,3000);
//fixSentence();
}
const fixSentence = () => {
let a = document.querySelector('.answer');
let think = document.querySelector('.think');
console.log('shown');
console.log(a.textContent);
let randomAnswer = randomAnswers[Math.floor(Math.random()*randomAnswers.length)];
var randomProperty = function (obj) {
var keys = Object.keys(obj)
let random = obj[keys[ keys.length * Math.random() << 0]];
return random/*[Math.floor(Math.random()*randomAnswers.length)]*/;
};
console.log(randomProperty(randomAnswers))
let splittedSentence = a.textContent.split(" ");
console.log(splittedSentence);
a.textContent = `${randomAnswer}`;
a.style.opacity = 1;
think.style.opacity = 0;
}
init();
}
the output of console.log(randomAnswer) is obviously undefined right now, but I can't figure out how to choose a random item out of one of the three arrays in the object.

You could do something like this:
const randomAnswers = {
goodAnswers: ['yes','Absolutely','certainly',"I'm sure",'HELL YES'],
maybes: ['maybe','probably','perhaps',"honestly man, i really don't know this one"],
badAnswers: ['LOL NO','no way man','maybe',"forget it",'HELL no','Are you serious?']
};
const randomNumber = function(subject) {
return Math.floor(Math.random()*subject.length);
}
const types = Object.keys(randomAnswers);
const randomTypeNumber = randomNumber(types);
const randomType = types[randomTypeNumber];
const randomAnswerNumber = randomNumber(randomAnswers[randomType]);
const randomAnswer = randomAnswers[randomType][randomAnswerNumber];
console.log( { randomType, randomAnswer } );
You pick a random key from the object, and then pick a random element from that array by using Object.keys(randomAnswers).length and subsequently that array length for the random numbers.

Related

How do i generate a random question using javascript for my quiz app which doesn't repeat the same question

I am trying to generate random questions from my "questions" object which does not repeat it's self but my quiz app is repeating questions.
Please forgive me if my question is not clear enough. This is my first ever time asking a question or really using stack overfolow,
let selectedQuestions = [];
//creates random index between 0 and the length of any array passed into it
const getRandomIndex = (arr) => Math.floor(Math.random() * arr.length);
//uses getRandomIndex to generate select a random object from and array. Also checks to see if the random object has been selected, if not, pushes the question to the empty selectedQuestions array and if selected, loops through its own function with a recursion by calling itself until it finds a question that has not already been pushed to the selectedQuestions array.
const getRandomObject = (arr) => {
const random = getRandomIndex(arr);
if (selectedQuestions.includes(random)) {
getRandomObject(arr);
}
selectedQuestions.push(random);
console.log("selected questions:", selectedQuestions.length)
return arr[random];
//renders the selected array and questions in the correct section of the quiz board.
const randomGenerator = () => {
const data = getRandomObject(questions);
progress.textContent = `Question ${gameState.questionCounter} of ${maxQuestion}`
questionBoard.textContent = `Q${gameState.questionCounter}. ${data.question}`;
currentCorrectAnswer = data.answer;
userAnswer.forEach((answer, index) => {
answer.innerHTML = `${alphabet[index]}. ${data.choices[index]}`;
});
currentUserAnswer = null;
clearAll()
gameState.questionCounter++
nextBtn.disabled = true;
setDisabledStateForQuizAnswers(false);
}
}
You're missing a return statement in the getRandomObject function.
if (selectedQuestions.includes(random)) {
return getRandomObject(arr);
}

Trying to push a pair of array values into a another array randomly without duplicates javascript

I'm trying to make an memory card game but this part is hard to figure out. I have an array with a deck of cards and I'm trying to select a specific amount cards in pairs randomly from the deck of cards and push them into the gameBoard array but I intitally keep getting duplicate of the pairs. Basically I trying to shuffle cards. I tried using a conditional statement but i dont know if this right way to go about this but it still doesnt work.
javascript
const deckOfCards = [
'card1',
'card2',
'card3',
'card4',
'card8',
'card9',
'card10',
'card11',
'card12',
'card13',
'card14',
]
let shuffle = deckOfCards[Math.floor(Math.random() * deckOfCards.length)];
let pair = [shuffle, shuffle]
let len = mode
for (let i = pair; i < deckOfCards.length; i++) {
if (gameBoard.indexOf(deckOfCards[i]) === -1) {
gameBoard.push(deckOfCards[pair])
}
}
console.log(gameBoard)
});
let gameBoard = []
just a thought: you can move the selected element to the back of the array and then randomly select stuff from a slice of the prior, unchanged array... just like array.slice(0, {a_number_here}.
something like this I guess (I cannot get your code working so this is not tested yet):
let shuffle = deckOfCards[Math.floor(Math.random() * deckOfCards.length - 5)]
name = deckOfCards.splice(shuffle, 1)
deckOfCards.push(name)
by the way if you can use libraries, just go for underscore.js and it would become very simple. just like this:
b = _.shuffle(deckOfCards).slice(0,5);
console.log(b)
you can also take a look at these repositories too (I haven't yet had the chance to take a look at them though but they kinda have a lot of stars so):
https://github.com/mmenavas/memory-game/blob/master/js/MemoryGame.js
https://github.com/code-sketch/memory-game
you can copy existing one to new one ex : const cloneSheepsES6 = [...sheeps];
then you can apply your condition without any duplications
This should give you an array of unique pair of cards.
const deckOfCards = [
"card1",
"card2",
"card3",
"card4",
"card8",
"card9",
"card10",
"card11",
"card12",
"card13",
"card14",
];
const randomArray = [];
let noOfPairs = 6; // No. of pairs required
while (noOfPairs) {
let randomNumber = Math.floor(Math.random() * deckOfCards.length);
if (randomArray.includes(randomNumber)) {
continue;
}
randomArray.push(randomNumber);
noOfPairs--;
}
randomArray.sort(() => 0.5 - Math.random());
const gameBoard = randomArray.map((item) => [
deckOfCards[item],
deckOfCards[item],
]);
console.log(gameBoard);

Function to format and add object to array not functioning properly

My component has a state array "bets" consisting of bet objects. The function in question creates an empty "records" array to house formatted records to be stored in the database.
const placeBets = () => {
//determine type of bet(s) - single,parlay,etc.
if(slipType === "single"){
let records = [];
bets.forEach(bet=>{
let tmpModel = formatSingleBet(bet)
records.push(tmpModel);
})
console.log(records);
}
}
I run a for each loop on the bets array to format each bet calling the formatSingleBet function.
//Function to format single bets in records for db storage
const formatSingleBet = (bet) =>{
//create instance of bet model obj and add properties
let betModel = model;
betModel.type = slipType;
betModel.wager = bet.wager;
betModel.odds = bet.odds.decimal;
betModel.result = "";
let legType = bet.type;
if(legType === "Spread"){
//create instance of spread line object
let spread = Spread;
spread.team.type = bet.team.type;
spread.team.name = bet.team.name;
spread.line = bet.handicap;
spread.result = "";
betModel.legs[0].fixtureID = bet.fixtureID;
betModel.legs[0].line = spread;
betModel.legs[0].odds = bet.odds.decimal;
}else if(legType === "3-Way Moneyline"){
//create instance of ML line object
let ml = ML;
ml.team.type = bet.team.type;
ml.team.name = bet.team.name;
ml.result = "";
betModel.legs[0].fixtureID = bet.fixtureID;
betModel.legs[0].line = ml;
betModel.legs[0].odds = bet.odds.decimal;
}else if(legType === "Total"){
//create instance of Total line object
let total = Total;
total.result = "";
total.bet = bet.bet;
total.line = bet.total;
betModel.legs[0].fixtureID = bet.fixtureID;
betModel.legs[0].line = total;
betModel.legs[0].odds = bet.odds.decimal;
}
return {
contestPlayerID: match.params.entryid,
jsonBet: betModel
};
}
I create an instance of the model object, and set the properties depending on the "leg type" of the bet. I then return the formatted bet to be inserted into the records array which is then returned.
The issue is that regardless of the differences in the bet, the betModel object is always returned as the last bet in the bets array.
One thing I noticed is that when I log the betModel it appears to be different for each bet, however the property values change when drilling into the object.
Please help, any advice would be wonderful.
By assigning betModel = model you are simply creating a reference to model and all the changes you make to betModel will also be made to model. This means that model is not a blank prototype, but contains the values of the last bet that you processed.
In order to use model as a prototype in the way you seem to intend use spread syntax to assign a copy to betModel.
let betModel = {...model}
const spreadSource = { a: 1, b: 2 };
const spread = {...spreadSource};
spread.c = 'Added'
console.log('spread: ', spread);
console.log('spreadSource: ', spreadSource);
const referenceSource = { a: 1, b: 2 };
const reference = referenceSource;
reference.c = 'Added';
console.log('reference: ', reference)
console.log('referenceSource: ', referenceSource)

Javascript Appending to 2-D Array

I am trying to append an array to an array. I am expecting the output to be something like:
[[Dep,POR],[14073,99.25],[14072,0.06]]
But I am getting:
Dep,POR,14073,99.25,14072,0.06
Here's what I have so far:
function get_historical() {
var well = document.getElementById('wellSelect');
var selected_well = well.options[well.selectedIndex].value;
var hist_json_obj = JSON.parse(Get("/get_historical/" + selected_well));
hist_por = ['Dep','POR'];
for (var item in hist_json_obj) {
if (hist_json_obj.hasOwnProperty(item)) {
var dep = hist_json_obj[item].dep;
var por = hist_json_obj[item].por;
var arr_por = [dep, parseFloat(por)];
hist_por.push(arr_por);
}
}
document.write(hist_por);
}
When you initialize hist_por, you want that to be a 2-D array whereas you currently have just a single array. So you would want to change its instantiation to:
hist_por = [['Dep','POR']]; // [[ ... ]] instead of [ ... ]
Also per #justrusty's answer, you need to JSON.stringify(hist_por) when you pass it to document.write(). This is the more important piece so his answer should be accepted.
So the whole code block would become:
function get_historical() {
var well = document.getElementById('wellSelect');
var selected_well = well.options[well.selectedIndex].value;
var hist_json_obj = JSON.parse(Get("/get_historical/" + selected_well));
hist_por = [['Dep','POR']];
for (var item in hist_json_obj) {
if (hist_json_obj.hasOwnProperty(item)) {
var dep = hist_json_obj[item].dep;
var por = hist_json_obj[item].por;
var arr_rop = [dep, parseFloat(por)];
hist_por.push(arr_por);
}
}
document.write(JSON.stringify(hist_por));
}
This may help you https://codepen.io/anon/pen/xQLzXx
var arr = ['foo','bar'];
var arr2 = ['baz', 'boo']
arr.push(arr2);
console.log(arr);
document.write(arr);
document.write("<br>");
document.write(JSON.stringify(arr));
It's basically just the way it writes it to document. If you log it in console you'll see the array appended. Or if you JSON.stringify() first it will show as you expect.
My advice is ALWAYS console.log() so you can see exactly how the data is structured
The others have already pointed out what the problem is (+ there's a typo in one of your variable names - arr_rop vs arr_por). Here's an ES6 version that will break in older browsers, for learning purposes:
function get_historical() {
const well = document.getElementById('wellSelect');
const selected_well = well.options[well.selectedIndex].value;
const hist_json_obj = JSON.parse(Get("/get_historical/" + selected_well));
const hist_por = Object.values(hist_json_obj).reduce(
(arr, item) => [...arr, [item.dep, +item.por]],
[["Dep", "POR"]]
);
document.write(JSON.stringify(hist_por));
}

JS Count occurrences in array and sort by highest

I'm trying to write a vote counting function, I have an array of objects and each object has a property called currentVote which has a userId value. I want to find out which userID has the most votes. Using lodash this is what I got so far:
function countVotes(players) {
return new Promise(function(resolve, reject) {
//votes should be empty, filled it with some sample values
let votes = ['312139659792875521','360445341989863434', '312139659792875521','360445341989863435','1','9999999999999999999999'];
for (let i = 0, j = players.length; i < j; i++) {
votes.push(players[i].currentVote);
}
let tally = _.chain(votes)
.countBy()
.toPairs()
.sortBy(1).reverse()
.map(0)
.value()[0];
resolve(tally);
});
How can I pick a random value IF I have multiple userIds with the same number of votes. At the moment it seems that the smallest ID will always be picked?
Based on your question, I believe your object is as follow, I have used the array method sort to sort the array in descending and picked up the first element. Hope this helps.
let players = [{
"userId":1,
"currentVotes":2220
},
{
"userId":2,
"currentVotes":383830
},
{
"userId":3,
"currentVotes":6894740
},
{
"userId":4,
"currentVotes":6894740
},
{
"userId":5,
"currentVotes":1
}
];
function getHighestVoteByRandowm(players){
let arrSameVotes = [];
let i = 0;
do{
arrSameVotes.push(players[i]);
temp = players[i].currentVotes;
i++;
}while(players[i].currentVotes == temp);
let rndTill = arrSameVotes.length - 1;
let rndVal = Math.round(Math.random() * rndTill);
return arrSameVotes[rndVal];
}
function sortVotes(a,b){
return b.currentVotes - a.currentVotes;
}
let highestVotesPlayer = getHighestVoteByRandowm(players.sort(sortVotes));
console.log(highestVotesPlayer);
You could use _.shuffle and _.first. Maybe something like:
_.chain(votes).countBy()
.groupBy() // added this to get a list of all the ones that have matching vote counts
.toPairs()
.sortBy(0)
.reverse()
.first() // most votes
.last() // get the user ids
.shuffle() // randomize order
.first() // get whatever is first
.value()

Categories

Resources