getting the same random index for 2 arrays - javascript

I am building a flashcard web app and I am trying to make a random japanese character appear but at the same time also have a english value to the character.
So I have two arrays (one English and one Japanese) and I have, with the help of someone on here managed to get the random Japanese letter to be displayed.
my question is how do I get the same index value for the english array to check an answer against without breaking the rest of my code?
// kana indexes
var kanaArray = ["あ","い","う","え","お","か","き","く","け","こ","さ","し","す","せ","そ","た","ち","つ",
"て","と","な","に","ぬ","ね","の","は","ひ","ふ","へ","ほ","ま","み","む","め","も","や","ゆ","よ","ら","り","る",
"れ","ろ","わ","を","ん"]
var kanaEng = ["a","i","u","e","o","ka","ki","ku","ke","ko","sa","shi","su","se","so","ta","chi","tsu",
"te","to","na","ni","nu","ne","no","ha","hi","fu","he","ho","ma","mi","mu","me","mo","ya","yu","yo","ra","ri","ru",
"re","ro","wa","wo","n"]
let getRandomKana = () => kanaArray[Math.floor(Math.random()*kanaArray.length-1)];
let getAnswerVal = kanaEng[Math.floor(Math.random()*kanaEng.length-1)];
//logic
var started = false;
var level = 0;
let kanaPassed = [];
// start and switch buttons
$(document).ready(function(){
$(".startBtn").click(function(){
started = true
$('.startBtn').css("visibility", 'hidden');
$('.switchBtn').css("visibility", 'visible');
$('h3').text(getRandomKana());
$('h3').css("visibility",'visible');
console.log(started)
})
});
$('.switchBtn').click(function(){
$('h3').text(getRandomKana());
});
// check answer
$('.submit').click(function(){
console.log(getAnswerVal);
if($('#answerBox').val()===getAnswerVal){
$('card').css('background-color','red');
}
});

You can make sure to get the first array index and use the same index on the second array so that you can get the same translation. some what like this:
const kanaArray = ["あ","い","う","え","お","か","き","く","け","こ","さ","し","す","せ","そ","た","ち","つ","て","と","な","に","ぬ","ね","の","は","ひ","ふ","へ","ほ","ま","み","む","め","も","や","ゆ","よ","ら","り","る","れ","ろ","わ","を","ん"];
const kanaEng = ["a","i","u","e","o","ka","ki","ku","ke","ko","sa","shi","su","se","so","ta","chi","tsu","te","to","na","ni","nu","ne","no","ha","hi","fu","he","ho","ma","mi","mu","me","mo","ya","yu","yo","ra","ri","ru","re","ro","wa","wo","n"];
const randomIndex = Math.floor(Math.random()*kanaArray.length);
const randomKanaArray = kanaArray[randomIndex];
const randomKanaEng = kanaEng[randomIndex];
Also you can make it more easier if you store it with JSON obj:
const KANAS = [{jap: "あ", eng: "a"},...];
const RANDOM_KANAS= KANAS[Math.floor(Math.random()*KANAS.length)];
console.log(RANDOM_KANAS.jap, RANDOM_KANAS.eng);

Related

how to get cell range values with background colors in to single array?

I tried to write the script as shown below. It is necessary to combine the values and background colors in this cell range into a single array. But it does not come as needed.
function newsheet(){
var app = SpreadsheetApp
var ss = app.getActiveSpreadsheet().getSheetByName("AddData");
//get category if checked
var catList = ss.getRange("I5:J31").getValues();
var catClrs = ss.getRange("J5:J31").getBackgrounds();
var c = catList.map((key,index) => ({[key]:catClrs[index]}));
Logger.log(c);
}
The answer comes this way
But I want an outcome like this.
[{Extra,true,#b6d7a8}, {Extra,false,#ffffff}, {Extra,false,#ffffff}, {Ldrain ,false,#ffffff}, {Dish Drain,true,#0c343d}, {U drain,true,#274e13}, {Hard Sholder,true,#00ffff}, {Soft Sholder,true,#cc0000}, {As. wearing,true,#ff9900}, {Tack coat Wearing,true,#fce5cd}, {As.Binder,true,#9900ff}, {Tack Coat binder,true,#46bdc6}, {Prime coat,true,#000000}, {ABC overlay,false,#ffffff}, {Subbase overlay,true,#980000}, {Edgewidning ABC,true,#999999}, {Edgewidning Subbase,false,#ffffff}, {SubGrade Ew,true,#0000ff}, {Embankment 5,true,#9fc5e8}, {Embankment 4,true,#6fa8dc}, {Embankment 3,true,#3d85c6}, {Embankment 2,true,#0b5394}, {Embankment 1,true,#1c4587}, {Subgrade Emb,true,#8e7cc3}, {Soft Ground tratment 1,true,#c27ba0}, {Soft Ground tratment 2,true,#a64d79}, {Clearing & grabbing,true,#f1c232}
I'd do it like this because it will be easier to read the values as you iterate through the array by having property labels for the object
function myobject(){
const ss=SpreadsheetApp.getActive()
var sh = ss.getSheetByName("AddData");
var catList = sh.getRange("I5:J31").getValues();
var catClrs = sh.getRange("J5:J31").getBackgrounds().flat();
let c=[];
catList.forEach((row,i) => {c.push({label:row[0],value:row[1],color:catClrs[i]})});
Logger.log(JSON.stringify(c));
}
With my fake data:
[{"label":3,"value":21,"color":"#ffffff"},{"label":0,"value":17,"color":"#ffffff"},{"label":5,"value":29,"color":"#ffffff"},{"label":29,"value":25,"color":"#ffffff"},{"label":16,"value":24,"color":"#ffffff"},{"label":17,"value":15,"color":"#ffffff"},{"label":22,"value":4,"color":"#ffffff"},{"label":6,"value":1,"color":"#ffffff"},{"label":4,"value":28,"color":"#ffffff"},{"label":14,"value":28,"color":"#ffffff"},{"label":13,"value":1,"color":"#ffffff"},{"label":2,"value":15,"color":"#ffffff"},{"label":23,"value":6,"color":"#ffffff"},{"label":14,"value":24,"color":"#ffffff"},{"label":21,"value":6,"color":"#ffffff"},{"label":12,"value":18,"color":"#ffffff"},{"label":12,"value":7,"color":"#ffffff"},{"label":5,"value":5,"color":"#ffffff"},{"label":2,"value":0,"color":"#ffffff"},{"label":16,"value":16,"color":"#ffffff"},{"label":15,"value":21,"color":"#ffffff"},{"label":0,"value":25,"color":"#ffffff"},{"label":20,"value":6,"color":"#ffffff"},{"label":24,"value":23,"color":"#ffffff"},{"label":22,"value":0,"color":"#ffffff"},{"label":14,"value":15,"color":"#ffffff"},{"label":24,"value":6,"color":"#ffffff"}]
Added flat()
Replaced key by row, index by i and ({[key]:catClrs[index]}) by [row[0],row[1],catClrs[i]]
function newsheet(){
var app = SpreadsheetApp
var ss = app.getActiveSpreadsheet().getSheetByName("AddData");
//get category if checked
var catList = ss.getRange("I5:J31").getValues();
var catClrs = ss.getRange("J5:J31").getBackgrounds().flat();
var c = catList.map((row,i) => [row[0],row[1],catClrs[i]]);
Logger.log(c);
}
The result will be slightly different because {} is used for objects and objects requires a key and a value.
I changed key by row to make the variable name closer to what it's holding as usually a "key" is a string but in this case it's an Array holding the values of two cells in the same row. i is shorter than index.
Nothing new compared to the accepted answer, but just shortening your code and a slighty better performance:
function newsheet(){
const ss = SpreadsheetApp.getActive().getSheetByName("AddData");
const range = ss.getRange("I5:J31");
const [catList,catClrs] = [range.getValues(),range.getBackgrounds()];
const c = catList.map((row,i) => [row[0],row[1],catClrs[0][i]]);
Logger.log(c);
}
If you want to filter on the true values:
function newsheet(){
const ss = SpreadsheetApp.getActive().getSheetByName("AddData");
const range = ss.getRange("I5:J31");
const [catList,catClrs] = [range.getValues(),range.getBackgrounds()];
const c = catList.map((row,i) => [row[0],row[1],catClrs[0][i]]).filter(r=>r[1]);
Logger.log(c);
}
Here is the code that worked correctly. In addition to what is mentioned in the question, the method of filtering is also included.
function newsheet(){
var app = SpreadsheetApp
var ss = app.getActiveSpreadsheet().getSheetByName("AddData");
//get category
var catList = ss.getRange("I5:J31").getValues();
var catClrs = ss.getRange("J5:J31").getBackgrounds().flat();
//merge arrays
var c = catList.map((row,i) => [row[0],row[1],catClrs[i]]);
//filter "checked" boxes values
var fillterC = c.filter(filterLogic);
}
//create filter logic function
var filterLogic =function(item){
if(item[1] === true){
return true;
}else{
return false;
}
}
Thanks to everyone who helped. I learned a lot.

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

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.

Why is this JavaScript looping twice in Zapier?

Here is a video that shows what I'm struggling with.
Here is a high level description of the process, followed by the actual JavaScript code I've written.
PROCESS
I built 2 Zaps that each run like this:
STEP 1 - Trigger (Cognito Form, which has repeating sections)
STEP 2 - JavaScript Code (which creates an Array of the form fields for ONE of the repeating sections, and separates them into individual strings using .split)
STEP 3 - Action (creates a ZOHO CRM Task for each string)
The first Zap runs on one of the sections of the form (Visits with Sales), and the second zap runs on a different section of the form (Visits without Sales). Each of these Zaps works fine on their own so I know the code is good, but I want to combine the two Zaps into one by combining the code.
I tried to combine by making five steps:
Trigger - Code1 - Zoho1 - Code2 - Zoho2
but the Zoho2 Tasks were each repeated
I then tried to re-order the five steps:
Trigger - Code1 - Code2 - Zoho1 - Zoho2
but now Zoho1 Tasks AND Zoho2 tasks were duplicated.
Finally I tried to combine ALL the JavaScript code into one:
Tigger - CombinedCode1+2 - Zoho 1 - Zoho2
but only the strings from Arrays in "Code2" are available to me when I go to map them in Zoho1.
CODE:
if (inputData.stringVSAccount == null) {
var listVSAccountArray = [];
var listVSUnitsArray = [];
var listVSPriceArray = [];
var listVSNotesArray = [];
var listVSVisitCallArray = [];
} else {
var listVSAccountArray = inputData.stringVSAccount.split(",");
var listVSUnitsArray = inputData.stringVSUnits.split(",");
var listVSPriceArray = inputData.stringVSPrice.split(",");
var listVSNotesArray = inputData.stringVSNotes.split(",");
var listVSVisitCallArray = inputData.stringVSVisitCall.split(",");
}
var output = [];
var arrayNos = listVSAccountArray.length;
var i = 0;
do {
var thisItemVSAccount = new String(listVSAccountArray[i]);
var thisItemVSUnits = new String(listVSUnitsArray[i]);
var thisItemVSPrice = new String(listVSPriceArray[i]);
var thisItemVSNotes = new String(listVSNotesArray[i]);
var thisItemVSVisitCall = new String(listVSVisitCallArray[i]);
var thisItemObj = {};
thisItemObj.itemVSAccount = thisItemVSAccount;
thisItemObj.itemVSUnits = thisItemVSUnits;
thisItemObj.itemVSPrice = thisItemVSPrice;
thisItemObj.itemVSNotes = thisItemVSNotes;
thisItemObj.itemVSVisitCall = thisItemVSVisitCall;
output.push({ thisItemObj });
i++;
} while (i < arrayNos);
//This is where the second zaps code is pasted in the combined version
if (inputData.stringOVAccount == null) {
var listOVAccountArray = [];
var listOVNotesArray = [];
var listOVVisitCallArray = [];
} else {
var listOVAccountArray = inputData.stringOVAccount.split(",");
var listOVNotesArray = inputData.stringOVNotes.split(",");
var listOVVisitCallArray = inputData.stringOVVisitCall.split(",");
}
var output = [];
var arrayNos = listOVAccountArray.length;
var i = 0;
do {
var thisItemOVAccount = new String(listOVAccountArray[i]);
var thisItemOVNotes = new String(listOVNotesArray[i]);
var thisItemOVVisitCall = new String(listOVVisitCallArray[i]);
var thisItemObj = {};
thisItemObj.itemOVAccount = thisItemOVAccount;
thisItemObj.itemOVNotes = thisItemOVNotes;
thisItemObj.itemOVVisitCall = thisItemOVVisitCall;
output.push({ thisItemObj });
i++;
} while (i < arrayNos);
I just started learning JavaScript this week, and sense that I am missing something obvious, perhaps a set of brackets. Thanks for any assistance
David here, from the Zapier Platform team. You're running into a confusing and largely undocumented feature where items after a code step run for each item returned. This is usually desired behavior - when you return 3 submissions you want to create 3 records.
In your case, it's also running subsequent unrelated actions multiple times, which sounds like it's undesired. In that case, it might be easier to have 2 zaps. Or, if "Zoho2" only ever happens once, put it first and let the branch happen downstream.
Separately, I've got some unsolicited javascript advice (since you mentioned you're a beginner). Check out Array.forEach (docs), which will let you iterate through arrays without having to manage as many variables (your own i every time). Also, try to use let and const over var when possible - it keeps your variables scoped as small as possible so you don't accidentally leak values into other areas.
​Let me know if you've got any other questions!
Just a note - you are declaring the same array variable output in both segments of your code block - the second declaration will be ignored.
Use the .forEach() method to iterate over your arrays, it will significantly cleanup you code. You also don't need to painstakingly construct the objects to be pushed into the output arrays.
This may not fix your issue but the code is far easier on the eye.
var listVSAccountArray = [],
listVSUnitsArray = [],
listVSPriceArray = [],
listVSNotesArray = [],
listVSVisitCallArray = [],
output = [];
if (typeof inputData.stringVSAccount === 'string') {
listVSAccountArray = inputData.stringVSAccount.split(',');
listVSUnitsArray = inputData.stringVSUnits.split(',');
listVSPriceArray = inputData.stringVSPrice.split(',');
listVSNotesArray = inputData.stringVSNotes.split(',');
listVSVisitCallArray = inputData.stringVSVisitCall.split(',');
}
// iterate over the array using forEach()
listVSAccountArray.forEach(function(elem, index){
// elem is listVSAccountArray[index]
output.push({
itemVSAccount: elem,
itemVSUnits: listVSUnitsArray[index],
itemVSPrice: listVSPriceArray[index],
itemVSNotes: listVSNotesArray[index],
itemVSVisitCall: listVSVisitCallArray[index]
})
})
//This is where the second zaps code is pasted in the combined version
var listOVAccountArray = [],
listOVNotesArray = [],
listOVVisitCallArray = [],
output_two = []; // changed the name of the second output array
if (typeof inputData.stringOVAccount === 'string') {
listOVAccountArray = inputData.stringOVAccount.split(',');
listOVNotesArray = inputData.stringOVNotes.split(',');
listOVVisitCallArray = inputData.stringOVVisitCall.split(',');
}
// iterate over the array using forEach()
listOVAccountArray.forEach(function(elem, index){
// elem is listOVAccountArray[index]
output_two.push({
itemOVAccount: elem,
itemOVNotes: listOVNotesArray[index],
itemOVVisitCall: listOVVisitCallArray[index]
});
});

Target Array Value Directly After Selected One

I'm really sorry for I am aware similar questions have already been asked, but whenever I try to do it myself, none seem to apply or work. Basically when a user clicks on one of the elements, I am trying to get the following variables:
the id of the selected element
an array with all of the values prior to selected + selected one
an array with all of the values post-selected (selected not included)
the id of the element directly following the selected one
Thanks to your help in different posts, I have so far managed to complete the first two ones (in italic), but am unable to achieve the other two.
Would anyone know how to do so please? Thank you all in advance for your help!!
jQuery:
var days = ['#monday','#tuesday','#wednesday','#thursday','#friday','#saturday','#sunday'];
$('.days').on('click', function() {
var day = '#'+this.id;
var index = days.indexOf(day)+1;
var prev = days.slice(0, index);
var next = days.slice(index);
var above = days[index];
});
Should look more like this (though I really don't understand your code logic):
var dayIds = ['monday','tuesday','wednesday','thursday','friday','saturday','sunday'];
$('.days').on('click', function() {
//get selected element id
var dayId = this.id;
//find selected position in array and delete all values after
var dayPos = dayIds.indexOf(dayId);
var daysBelow = dayIds.slice(0, dayPos + 1;
//find position of item directly after selected and get value
var dayAfterPos = dayIds.indexOf(dayId) + 1;
var dayAfter = dayIds[dayAfterPos]; //(not working)
//only keep values following selected one
...
console.log(floorsBelow, floorId);
});
This is how you need to slicing the array. I'm not sure all the requirements you have so I have just taken out a snippet to demonstrate how you can get your values.
var dayIds = new Array('#monday','#tuesday','#wednesday','#thursday','#friday','#saturday','#sunday');
const current = '#thursday';
const currentIndex = dayIds.indexOf(current)+1;
const prev = dayIds.slice(0, currentIndex);
const next = dayIds.slice(currentIndex);
console.log(current); //#thursday
console.log(prev); //[ '#monday', '#tuesday', '#wednesday', '#thursday' ]
console.log(next); // [ '#friday', '#saturday', '#sunday' ]
EDIT:
Added newVar to contain next value
var dayIds = new Array('#monday','#tuesday','#wednesday','#thursday','#friday','#saturday','#sunday');
const current = '#thursday';
const currentIndex = dayIds.indexOf(current)+1;
const prev = dayIds.slice(0, currentIndex);
const next = dayIds.slice(currentIndex);
const newVar = dayIds[currentIndex];
console.log(current); //#thursday
console.log(prev); //[ '#monday', '#tuesday', '#wednesday', '#thursday' ]
console.log(next); // [ '#friday', '#saturday', '#sunday' ]
console.log(newVar); // #friday

Return the first two string with a matching keyword

I get returned and aggregated list that is a string. I only want to display two items and remove the rest. Looking to do this in javascript.
I have something that looks like this:
"type:of:pets:pet:304126008:pet:328464062:pet:329003654:pet:274825265:pet:302508993"
I want to return the first two pets and strip off the rest:
"type:of:pets:pet:304126008:pet:328464062"
I tried to do something like:
var types = "type:of:pets:pet:304126008:pet:328464062:pet:329003654:pet:274825265:pet:302508993"
types.split('type:of:pets:pet', 2);
Looks like it doesnt take account of the numbers that I need as well.
You can slice 7 words, so that you keep 3 first words and 2 following pairs.
const types = "type:of:pets:pet:304126008:pet:328464062:pet:329003654:pet:274825265:pet:302508993";
const r = types.split(':').slice(0, 7).join(':');
console.log(r)
Swap const to var if needed for es5 compatibility.
const input = 'type:of:pets:pet:304126008:pet:328464062:pet:329003654:pet:274825265:pet:302508993';
const start = 'type:of:pets';
const petDelimiter = ':pet:';
const pets = input.substr(start.length + petDelimiter.length).split(petDelimiter);
const result = start + pets.slice(0, 2).map(pet => petDelimiter + pet).join('');
console.log(result)
Use a regex:
var pets = "type:of:pets:pet:304126008:pet:328464062:pet:329003654:pet:274825265:pet:302508993".match(/(pet:[0-9]+)/g);
console.log("type:of:pets:" + pets.slice(0, 2).join(":"));

Categories

Resources