New to JavaScript and think I need a loop for this.....? - javascript

I've got a 180 character string of numbers which needed to be broken down into 6 groups, separated into 2 character figures and then sorted into ascending order.
I've done this, but it looks dirty and I'm pretty sure with my gradual improvement of understanding of JavaScript, that a neat little loop would save me a huge amount of repetition.
<script type="text/javascript">
var ticketString = "011722475204365360702637497481233455758302154058881928446789061241507324334876840738576186051132437816395663800818206590104559628214294664710935667287132130687703253151692742547985".match(/.{1,2}/g);
var groupa = ticketString.slice (0,15);
groupa.sort();
var groupb = ticketString.slice (15,30);
groupb.sort();
var groupc = ticketString.slice (30,45);
groupc.sort();
var groupd = ticketString.slice(45,60);
groupd.sort();
var groupe = ticketString.slice(60,75);
groupe.sort();
var groupf = ticketString.slice(75,90);
groupf.sort();
function displayArray () {
document.getElementById('ticketOne').innerHTML = groupa;
document.getElementById('ticketTwo').innerHTML = groupb;
document.getElementById('ticketThree').innerHTML = groupc;
document.getElementById('ticketFour').innerHTML = groupd;
document.getElementById('ticketFive').innerHTML = groupe;
document.getElementById('ticketSix').innerHTML = groupf;
}
The outputs are placed into paragraphs for now, but I know this could be done easier than the way I have it. The function displayArray loads off the body tag.

If you could rename your elements from ticketOne, ticketTwo etc to ticket1, ticket2 etc:
<script type="text/javascript">
var ticketString = "011722475204365360702637497481233455758302154058881928446789061241507324334876840738576186051132437816395663800818206590104559628214294664710935667287132130687703253151692742547985".match(/.{1,2}/g);
for (var i=0; i<ticketString.length/15; i++) {
var group = ticketString.slice(i*15, i*15+15);
group.sort();
document.getElementById('ticket'+(i+1)).innerHTML = group;
}
</script>

So here is what I think is the best solution:
var ticketString = "011722475204365360702637497481233455758302154058881928446789061241507324334876840738576186051132437816395663800818206590104559628214294664710935667287132130687703253151692742547985".match(/.{1,2}/g);
var group = [];
for (var i = 0; i < 180 / 15 / 2; i++) {
group[i] = ticketString.slice(i * 15, (i + 1) * 15);
group[i].sort();
document.getElementById('ticket[' + i + ']').innerHTML = group[i];
}
What I'm doing here is that I created a local array called group, which is in turn easier to handle within a loop than using a name like "group1" or "ticketFirst".
After that I practically did the same you did, but since I used the for loop I was able to short it down significantly.
The reason why I used i < 180 / 15 / 2 is because you're pairing them in character packs of 2. for (var i = 0; i < 180 / 15 / 2; i++) You ofcourse have to have an HTML like this:
<body>
<p id="ticket[0]"></p>
<p id="ticket[1]"></p>
<p id="ticket[2]"></p>
<p id="ticket[3]"></p>
<p id="ticket[4]"></p>
<p id="ticket[5]"></p>
</body>

You can reduce it to:
var groupArray = [];
for(var i=0;i<100;i+=15){
groupArray.push(ticketString.slice (i,15+i));
groupArray[groupArray.length-1].sort();
}

You could do something like this, if you changed your 'ticket' id's to a generic 'ticket' class;
var ticketString = "011722475204365360702637497481233455758302154058881928446789061241507324334876840738576186051132437816395663800818206590104559628214294664710935667287132130687703253151692742547985".match(/.{1,2}/g);
var tickElem = document.querySelectorAll('.ticket');
var strPoint = 0;
for(var i in tickElem)
{
var grp = ticketString.slice(strPoint, (strPoint += 15));
grp.sort();
tickElem[i].innerText = grp.join('');
}

How about this compact version:
var start = 0;
['ticketOne', 'ticketTwo', 'ticketThree', 'ticketFour', 'ticketFive', 'ticketSix']
.forEach(function (id) {
document.getElementById(id).innerHTML = ticketString.slice(start, start += 15).sort();
});

<script>
var ticketString ="011722475204365360702637497481233455758302154058881928446789061241507324334876840738576186051132437816395663800818206590104559628214294664710935667287132130687703253151692742547985".match(/.{1,2}/g);
function loadTickets () {
var ticket = [];
for (var i = 0; i < ticketString.length / 15; i++) {
ticket[i] = ticketString.slice(i * 15, (i + 1) * 15).sort();
var tableCre = document.createElement("TABLE");
tableCre.setAttribute("id","ticketTable" + i)
document.body.appendChild(tableCre);
document.getElementById('ticketTable' + i).innerHTML = ticket[i];
}
console.log(ticketString);
console.log(ticket);
};
</script>
Got it fixed, #Quikers - given you the thumbs up; as this was the thinking I had - brought the .sort() function into the ticket[i] variable to trim it a little and based on the number of arrays, I have dynamically created 6 tables that hold the strings inside them. I have to develop the tables and set them up, but I am pretty much there now. Thanks for all your help.

Related

Javascript file isn't appending to a filtered list

As the title reads, my javascript file won't append to a filtered list via a random generator function, for context it's being built in replit so perhaps its just a buggy bit of software on replits end, though I'm certain I've done something wrong and can't for the life of me figure out what. The main idea for this project is to have it randomly select an item from a list, append it to an empty list, then pass that string to an HTML textarea tag to be displayed as text.
Code in question:
var LowercaseList = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"];
var NumList = ["1","2","3","4","5","6","7","8","9","0"];
var SpecialCharList = ["`","~","!","#","$","%","^","&","*","_","-","+","=","<",">","?","/"];
// Letter list ID's since I couldn't figure out how to run this using a database
var LetterIDList = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26];
// Number list ID's since I couldn't figure out how to run this using a database
var NumIDList = [1,2,3,4,5,6,7,8,9,10];
// Special character list ID's since I couldn't figure out how to run this using a database
var SpecialID = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17];
// Filtered Lists
var UpperFiltered = [];
var LowerFiltered = [];
var NumFiltered = [];
var SpecialFiltered = [];
// Global declarations of random number variables to grab values from intial lists
var UpperGenVariable;
var LowerGenVariable;
var NumGenVariable;
var SpecialGenVariable;
// Creates a basic password with 2 of each kind of character
function Basic () {
for (var i = 1; i < 2; i++) {
UppercaseGenerate();
}
for (var i = 1; i < 2; i++) {
LowercaseGenerate();
}
for (var i = 1; i < 2; i++) {
NumGenerate();
}
for (var i = 1; i < 2; i++) {
SpecialGenerate();
}
};
let passwordGen = document.getElementById("PasswordDisplay")
function UppercaseGenerate () {
var UpperFiltered = [];
UpperGenVariable = Math.random(0, LetterIDList.length);
for (var i = 0; i < LetterIDList.length - 1; i++) {
if (LetterIDList[i] == UpperGenVariable) {
appendItem(UpperFiltered, UppercaseList[i]);
}
};
console.log(UpperFiltered);
passwordGen.value = UpperFiltered
};
HTML textarea code:
<label style = "color:white;" for="PasswordDisplay">Your generated password ----></label>
<textarea readonly id="PasswordDisplay" name="PasswordDisplay" rows="10" cols="50">
Please select a password complexity setting
</textarea>
I changed how you generate the random number.
Also added the UppercaseList, added i <= 2 rather then i < 2 in the cycles so the yould really run 2 times, added += to passwordGen.value += UpperFiltered so the value would add up.
I guess that is it.
var UppercaseList = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
var LowercaseList = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"];
var NumList = ["1","2","3","4","5","6","7","8","9","0"];
var SpecialCharList = ["`","~","!","#","$","%","^","&","*","_","-","+","=","<",">","?","/"];
// Letter list ID's since I couldn't figure out how to run this using a database
var LetterIDList = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26];
// Number list ID's since I couldn't figure out how to run this using a database
var NumIDList = [1,2,3,4,5,6,7,8,9,10];
// Special character list ID's since I couldn't figure out how to run this using a database
var SpecialID = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17];
// Filtered Lists
var UpperFiltered = [];
var LowerFiltered = [];
var NumFiltered = [];
var SpecialFiltered = [];
// Global declarations of random number variables to grab values from intial lists
var UpperGenVariable;
var LowerGenVariable;
var NumGenVariable;
var SpecialGenVariable;
// Creates a basic password with 2 of each kind of character
function Basic () {
for (var i = 1; i <= 2; i++) {
UppercaseGenerate();
}
for (var i = 1; i <= 2; i++) {
LowercaseGenerate();
}
for (var i = 1; i <= 2; i++) {
NumGenerate();
}
for (var i = 1; i <= 2; i++) {
SpecialGenerate();
}
};
let passwordGen = document.getElementById("PasswordDisplay")
function UppercaseGenerate() {
var UpperFiltered = [];
UpperGenVariable = Math.floor(Math.random() * LetterIDList.length);
for (var i = 0; i < LetterIDList.length; i++) {
if (LetterIDList[i] == UpperGenVariable) {
UpperFiltered.push(UppercaseList[i]);
}
};
passwordGen.value += UpperFiltered
};

filter with object references lodash

I have an array, I need to chunk that array & manipulate parts of the chunks BUT I'd like to it to update my original array
I'm self taught with no computer science background so when it comes to technical inner workings I'm at a disadvantage.
var markers = ["one","two","three","four","five","six","seven","eight","nine"]
var chunks = _.chunk(markers, 5)
var result = _.chain(chunks[0]).last().value();
result = 'newValue'
console.log(chunks);
console.log(markers);
//was hopping to get
// ["one","two","three","four","newValue","six","seven","eight","nine"]
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.min.js"></script>
I'm not quite sure I got your requirement right, but this changes the first and last element of each "chunk" (without really splitting the array).
var data = [
"one","two","three","four","five",
"one","two","three","four","five",
"one","two","three"
];
var chunkSize = 5,
numberOfChunks = Math.ceil(data.length / chunkSize),
indexOfFirstElementInChunk,
indexOfLastElementInChunk;
for (var i = 0; i < numberOfChunks; i++) {
indexOfFirstElementInChunk = (i * chunkSize);
data[indexOfFirstElementInChunk] = "first element";
indexOfLastElementInChunk = Math.min(data.length, ((i + 1) * chunkSize)) - 1;
if (indexOfFirstElementInChunk < indexOfLastElementInChunk) {
data[indexOfLastElementInChunk] = "last element";
}
}
console.log(data);

Loop through array of images in javascript

I'm trying to loop through an array of images but can't seem to get past image 2.
The array should also loop back to 1 when the last image has passed...
var WorkArray = new Array('work/01.png', 'work/02.png', 'work/03.png', 'work/04.png');
var nelements = WorkArray.length;
preload_image_object = new Image();
var i = 0;
for(i=0; i<=nelements; i++) {
preload_image_object.src = WorkArray[i];
}
function cC() {
var nelements = WorkArray.length;
var i = 0;
for(i=0; i<=nelements; i++) {
nelements = WorkArray[i];
}
document.getElementById("work").style.backgroundImage="url('"+WorkArray[i]+"')";
}
You can save the current file and use modulo to run in cyclic manner.
It will look something like that:
var WorkArray = new Array('work/01.png', 'work/02.png', 'work/03.png', 'work/04.png');
var currentImage = 0
function nextImage(){
currentImage = (currentImage + 1) % WorkArray.length;
document.getElementById("work").style.backgroundImage="url('"+WorkArray[currentImage]+"')";
}
You are overwriting nelements with the current element of the loop:
nelements = WorkArray[i];
The following should fix your loops:
var WorkArray = new Array('work/01.png', 'work/02.png', 'work/03.png', 'work/04.png');
var preload_image_object = new Image();
/* Lets get rid of `nelements`, as its just confusing. Get the length here.
* If, for performace reasons you want to use elements, the best way is to reverse
* aka for(var i = WorkArray.length-1; i >= 0 ; i--)
* Also, its simpler to declare the var in your for-loop itself instead of outside of it.
*/
for(var i = 0; i <= WorkArray.length; i++){
preload_image_object.src = WorkArray[i];
}
Also, again for simplifications sake, your application of the background-image could be done inside your for loop as well, and can be made to look cleaner with some spaces and omitting the ' inside your url():
document.getElementById("work").style.backgroundImage = "url(" + WorkArray[i] + ")";

I want to add all the values in the field Sum to the field Total but it is not working

Here, sums[i].value is getting right values but when I want to keep a grand total of all Sum, it is failing.
function calc() {
var amounts = document.getElementsByName("Amount");
var prices = document.getElementsByName("Price");
var sums = document.getElementsByName('Sum');
var tax = document.getElementsByName('Tax');
var total = document.getElementsByName('Total');
for (var i = 0; i < amounts.length; i++) {
sums[i].value = amounts[i].value * prices[i].value;
total[0].value = total[0].value + sums[i].value;
// only this line is not working
}
}
Plain HTML is strings, all the way down, and var amounts = document.getElementsByName("Amount"); followed by amounts.value means you now have string values. Since + is also a string operator, JavaScript will happily turn "2"+"4" into "24", which looks like it did maths, but wrong, when in fact it didn't do math at all.
Convert all values that need to be numbers into numbers, first:
var amounts = document.getElementsByName("Amount");
....
var amount = parseFloat(amounts.value); // NOW it's a number
...
Replace your code with :
for (var i = 0; i < amounts.length; i++) {
sums[i].value = parseFloat(amounts[i].value) * parseFloat(prices[i].value);
total[0].value = parseFloat(total[0].value) + parseFloat(sums[i].value);
// only this line is not working
}
sums[i].value = parseFloat(amounts[i].value) * parseFloat(prices[i].value);
total[0].value = parseFloat(total[0].value) + parseFloat(sums[i].value);
This should help you.
Remove the .value while adding and multiplying
function test()
{
var amounts = new Array();
amounts[0] = "4";
amounts[1] = "6";
amounts[2] = "10";
var prices = new Array();
prices[0] = "4";
prices[1] = "6";
prices[2] = "10";
var sums = new Array();
var total = 0;
for (var i = 0; i < amounts.length; i++) {
sums[i] = parseInt(amounts[i]) * parseInt(prices[i]);
total= parseInt(total) + parseInt(sums[i]);
// only this line is not working
//alert(total); is 152
}
}

Javascript Random problem?

var swf=["1.swf","2.swf","3.swf"];
var i = Math.floor(Math.random()*swf.length);
alert(swf[i]); // swf[1] >> 2.swf
This case ,Random output One number.
How to Random output two different numbers ?
var swf = ['1.swf', '2.swf', '3.swf'],
// shuffle
swf = swf.sort(function () { return Math.floor(Math.random() * 3) - 1; });
// use swf[0]
// use swf[1]
Even though the above should work fine, for academical correctness and highest performance and compatibility, you may want to shuffle like this instead:
var n = swf.length;
for(var i = n - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var tmp = swf[i];
swf[i] = swf[j];
swf[j] = tmp;
}
Credits to tvanfosson and Fisher/Yates. :)
You can use splice to remove the chosen element, then simply select another randomly. The following leaves the original array intact, but if that's not necessary you can use the original and omit the copy. Shown using a loop to demonstrate how to select an arbitrary number of times upto the size of the original array.
var swf=["1.swf","2.swf","3.swf"];
var elementsToChoose = 2;
var copy = swf.slice(0);
var chosen = [];
for (var j = 0; j < elementsToChoose && copy.length; ++j) {
var i = Math.floor(Math.random()*copy.length);
chosen.push( copy.splice(i,1) );
}
for (var j = 0, len = chosen.length; j < len; ++j) {
alert(chosen[j]);
}
I would prefer this way as the bounds are known (you are not getting a random number and comparing it what you already have. It could loop 1 or 1000 times).
var swf = ['1.swf', '2.swf', '3.swf'],
length = swf.length,
i = Math.floor(Math.random() * length);
firstRandom = swf[i];
// I originally used `delete` operator here. It doesn't remove the member, just
// set its value to `undefined`. Using `splice` is the correct way to do it.
swf.splice(i, 1);
length--;
var j = Math.floor(Math.random() * length),
secondRandom = swf[j];
alert(firstRandom + ' - ' + secondRandom);
Patrick DW informed me of delete operator just leaving the value as undefined. I did some Googling and came up with this alternate solution.
Be sure to check Tvanfosson's answer or Deceze's answer for cleaner/alternate solutions.
This is what I would do to require two numbers to be different (could be better answer out there)
var swf=["1.swf","2.swf","3.swf"];
var i = Math.floor(Math.random()*swf.length);
var j;
do {
j = Math.floor(Math.random()*swf.length);
} while (j === i);
alert(swf[i]);
alert(swf[j]);
Edit: should be j===i

Categories

Resources