better solution than a switch for change classNames - javascript

I have created a clock, that connected to date().getHours / minutes /Seconds
The images that are shows are embedded in different classes.
Now when i want to change the images i wrote a switch for every second minute and hours..
Thats probably more code than googles engine. So i wonder if there is a more simple solution.
This is some code of the hour switch
so when minute 15 gets to the clock it change the className to one and five.
switch(h){
case 15:
x = hours.appendChild(hour1).className = "clock-digit-one";
x = hours.appendChild(hour2).className = "clock-digit-five";
break
case 16:
x = hours.appendChild(hour1).className = "clock-digit-one";
x = hours.appendChild(hour2).className = "clock-digit-six";
break
default:
x = hours.appendChild(hour1).className = "clock-digit-zero";
x = hours.appendChild(hour2).className = "clock-digit-zero";
}
I have created a jsFiddle that shows more of the code.
Any tips would be great.
http://jsfiddle.net/Xk49c/2/
Thanks

Create an array of human-readable numbers:
var digits = ["zero", "one", "two", ..., "nine"];
Break down h into first and second digit:
var hours = Math.floor(h / 10);
var minutes = h % 10;
Index into digits to determine the class name you should be using:
hours.appendChild(hour1).className = "clock-digit-" + digits[hours];
hours.appendChild(hour2).className = "clock-digit-" + digits[minutes];

Of course there is a simpler solution. For example, you can make class names such as clock-digit-[number] and then use string concatnation to make the className:
x = hours.appendChild(hour1).className = "clock-digit-"+h;
To find out form which digits the time number consists, you can convert the number to string and .split() it. This is not the most effective way, but its simple and clear.
var numbers = h.toString().split(""); //Will give ["1","5"] for 15
Then you add numbers to your div using for loop:
for(var i=0; i<numbers.length; i++) { //We loop through ["1","5"]
var num = document.createElement("div"); //Use your element type here!
num.className = "clock-digit-"+numbers[i]; //Get either 1 or 5
hours.appendChild(num);
}
In case you wanted to use the original class names, you can create an Array, like #Jon proposed:
var digits = ["zero", "one", "two", ..., "nine"];
Then, the for loop would look like that:
for(var i=0; i<numbers.length; i++) { //We loop through ["1","5"]
var num = document.createElement("div"); //Use your element type here!
num.className = "clock-digit-"+digits[numbers[i]]; //Get either 1 or 5
hours.appendChild(num);
}

just expanding my initial comment
var digits = new Array("zero","one","two","three","four","five","six","seven","eight","nine");
var h=new Date().getHours().toString();
var m = new Date().getMinutes().toString();
var s = new Date().getSeconds().toString();
var t = ((h>9?h:"0"+h)+ (m>9?m:"0"+m) +(s>9?s:"0"+s));
hours.appendChild(hour1).className = "clock-digit-" + digits[t.substring(0,0+1)];
hours.appendChild(hour2).className = "clock-digit-" + digits[t.substring(1,1+1)];
minutes.appendChild(minute1).className = "clock-digit-" + digits[t.substring(2,2+1)];
minutes.appendChild(minute2).className = "clock-digit-" + digits[t.substring(3,3+1)];
seconds.appendChild(second1).className = "clock-digit-" + digits[t.substring(4,4+1)];
seconds.appendChild(second2).className = "clock-digit-" + digits[t.substring(5,5+1)];

I would suggest a solution that keeps an associative array of digits to their associated classes. Then you only need two lines to set each digit (instead of every single combination of two digits individually)
Something along these lines:
var digitToClass = {
0: 'clock-digit-zero',
1: 'clock-digit-one',
2: 'clock-digit-two',
3: 'clock-digit-three'
//..
};
var minute = "03";
minutes1.className = digitToClass[minute[0]];
minutes2.className = digitToClass[minute[1]];

Create an array of the class names and refer to its index (60 items), that's better than a switch.
EDIT: Others have posted examples and better solutions, but the logic is that an array is the best solution.

Related

Generate string of random number that includes some number and exclude some number

I have a problem about generating string in javascript.
I have an array of number that string should contains atleast 1, and 1 number(up to 7 digits) that must not contains in a string. String length must be 7.
var incNumber = ["15","51","14","41","55","39","23"];
var exclude = ... //input from user
I tried to generate it by random select from array, random position and random other number around selected number. Then check if string contains excluded number, generate it again.
//random select number
var getRandom = incNumber[Math.floor(Math.random() * incNumber.length)];
//random position of number
var position = Math.floor(Math.random() * 6);
//length of other string after selected number
var afterlen = 7 - (position+2);
//genNum(...) is my function that use to generate string of number in specific length.
var nstr = genNum(position)+getRandom+genNum(afterlen);
while (nstr.includes(exclude)) {
nstr = genNum(position)+getRandom+genNum(afterlen);
}
but doing this take too long time or sometimes freeze my browser. How should I fix it.?
edited: It's my homework about phonenumber.
final string should be like "37915002"
Edited my code again
Does that now match your needs? It has got pretty messy and I'm not sure if it's correct (I'm never sure.. xD) hope you can get some inspiration though.
// Variables
var initialList = ["100", "5", "19", "88", "10", "90"];
var excludeList = ["9", "10"];
var resultLength = 7;
var finalString = "";
// Create a third final array that is filtered
var finalList = initialList.filter(element => {
let shouldBeIncluded = true;
excludeList.forEach(excluder => {
Array.from(excluder).forEach(excluderFragment => {
if (element.includes(excluderFragment)) shouldBeIncluded = false;
});
});
if (shouldBeIncluded) return true;
});
// Check if all were excluded
if (finalList.length == 0) {
// Do error handling here
} else {
// Create the list
for (let i = 0; i < resultLength; i++) {
finalString += finalList[Math.floor(Math.random() * finalList.length)];
}
// Shorten the list because multiple digits values
finalString = finalString.slice(0, 7);
console.log(finalString);
}
You could start by filtering the unwanted number from the incNumber and doing everything the same way but on the new array
var incNumber = ["15","51","14","41","55","39","23"];
var exclude = "12";
var filteredNumbber =incNumber.filter(number=> number!==exclude);
var random = filteredNumbber[Math.floor(Math.random() * filteredNumbber.length)];
if we assume exclude is not a value but instead an array of values you would change the formula to
var incNumber = ["15","51","14","41","55","39","23"];
var exclude = ["15"];
var filteredNumbber =incNumber.filter(number=> !exclude.includes(number));
var random = filteredNumbber[Math.floor(Math.random() * filteredNumbber.length)];
as some people suggested random variable may end up as undefined if we exclude all the numbers inside of incNumber, if that was the case we should add an additional check in case that happens
if (random!==undefined) var nstr = genNum(position)+random+genNum(afterlen);

Manipulate more javascript array based on another array

I've a strange thing to do but I don't know how to start
I start with this vars
var base = [1,1,1,2,3,5,7,9,14,19,28,40,56,114,232,330];
var sky = [0,0,0,3,4,5,6,7,8,9,10,11,12,14,16,17];
var ite = [64,52,23,38,13,15,6,4,6,3,2,1,2,1,1,1];
So to start all the 3 array have the same length and the very first operation is to see if there is a duplicate value in sky array, in this case the 0 is duplicated and only in this case is at the end, but all of time the sky array is sorted. So I've to remove all the duplicate (in this case 0) from sky and remove the corresponding items from base and sum the corresponding items on ite. So if there's duplicate on position 4,5 I've to manipulate this conditions. But let see the new 3 array:
var new_base = [1,2,3,5,7,9,14,19,28,40,56,114,232,330];
var new_sky = [0,3,4,5,6,7,8,9,10,11,12,14,16,17];
var new_ite = [139,38,13,15,6,4,6,3,2,1,2,1,1,1];
If you see the new_ite have 139 instead the 64,52,23, that is the sum of 64+52+23, because the first 3 items on sky are the same (0) so I remove two corresponding value from base and sky too and I sum the corresponding value into the new_ite array.
There's a fast way to do that? I thought a for loops but I stuck at the very first for (i = 0; i < sky.length; i++) lol, cuz I've no idea on how to manipulate those 3 array in that way
J
When removing elements from an array during a loop, the trick is to start at the end and move to the front. It makes many things easier.
for( var i = sky.length-1; i>=0; i--) {
if (sky[i] == prev) {
// Remove previous index from base, sky
// See http://stackoverflow.com/questions/5767325/how-to-remove-a-particular-element-from-an-array-in-javascript
base.splice(i+1, 1);
sky.splice(i+1, 1);
// Do sum, then remove
ite[i] += ite[i+1];
ite.splice(i+1, 1);
}
prev = sky[i];
}
I won't speak to whether this is the "fastest", but it does work, and it's "fast" in terms of requiring little programmer time to write and understand. (Which is often the most important kind of fast.)
I would suggest this solution where j is used as index for the new arrays, and i for the original arrays:
var base = [1,1,1,2,3,5,7,9,14,19,28,40,56,114,232,330];
var sky = [0,0,0,3,4,5,6,7,8,9,10,11,12,14,16,17];
var ite = [64,52,23,38,13,15,6,4,6,3,2,1,2,1,1,1];
var new_base = [], new_sky = [], new_ite = [];
var j = -1;
sky.forEach(function (sk, i) {
if (!i || sk !== sky[i-1]) {
new_ite[++j] = 0;
new_base[j] = base[i];
new_sky[j] = sk;
}
new_ite[j] += ite[i];
});
console.log('new_base = ' + new_base);
console.log('new_sky = ' + new_sky);
console.log('new_ite = ' + new_ite);
You can use Array#reduce to create new arrays from the originals according to the rules:
var base = [1,1,1,2,3,5,7,9,14,19,28,40,56,114,232,330];
var sky = [0,0,0,3,4,5,6,7,8,9,10,11,12,14,16,17];
var ite = [64,52,23,38,13,15,6,4,6,3,2,1,2,1,1,1];
var result = sky.reduce(function(r, n, i) {
var last = r.sky.length - 1;
if(n === r.sky[last]) {
r.ite[last] += ite[i];
} else {
r.base.push(base[i]);
r.sky.push(n);
r.ite.push(ite[i]);
}
return r;
}, { base: [], sky: [], ite: [] });
console.log('new base:', result.base.join(','));
console.log('new sky:', result.sky.join(','));
console.log('new ite:', result.ite.join(','));
atltag's answer is fastest. Please see:
https://repl.it/FBpo/5
Just with a single .reduce() in O(n) time you can do as follows; (I have used array destructuring at the assignment part. One might choose to use three .push()s though)
var base = [1,1,1,2,3,5,7,9,14,19,28,40,56,114,232,330],
sky = [0,0,0,3,4,5,6,7,8,9,10,11,12,14,16,17],
ite = [64,52,23,38,13,15,6,4,6,3,2,1,2,1,1,1],
results = sky.reduce((r,c,i) => c === r[1][r[1].length-1] ? (r[2][r[2].length-1] += ite[i],r)
: ([r[0][r[0].length],r[1][r[1].length],r[2][r[2].length]] = [base[i],c,ite[i]],r),[[],[],[]]);
console.log(JSON.stringify(results));

Number of combinations in a given number array in javascript

var ans = (49*48*47*46*45*44)/(6*5*4*3*2*1)
alert(ans.toLocaleString())
This will output 13,983,816 and it's the correct number of possible combinations from a number array of 1 to 49.
How do I implement this with numbers that I can get from 2 variables?
For example if I want to calculate the number of combinations possible for 5 numbers out of 40 I need to have (40*39*38*37*36)/(5*4*3*2*1) and I need this to be replaced like: 40*39*38*37*36 with var n and (5*4*3*2*1) with var t but output the correct order of numbers.
Just to be clear, I don't want to write these operations manually in the variables, I want the number specified in the variables to generate the operations based on their value. If I specify 6 selections I need to generate 6*5*4*3*2*1, if I specify 5 selections it needs to generate 5*4*3*2*1 and so on.
Thanks for the help!
Updated, (with loops):
Number.prototype.to = function(to){
var result = 1;
while(this >= to) result *= to++;
return result
};
var n = 49..to(44); //49*48*47*46*45*44
var t = 6..to(1); //6*5*4*3*2*1
document.writeln((n/t).toLocaleString())
You can try for loops:
function binom(a,b) {
if(a < 2*b) b = a-b;
var n = 1;
for(var i=a-b+1; i<=a; ++i) n *= i;
for(var i=2; i<=b; ++i) n /= i;
return n;
}
Nevermind, I managed to figure it out after some good hours:
function getChance(numbers, out_of) {
return numbers>0?out_of/numbers*getChance(numbers-1,out_of-1):1;
}
var np = 6; //numbers picked
var tn = 49; //total numbers
var ntm = 6; //numbers to match
var picks = getChance(np-ntm, tn-ntm);
var combs = getChance(np, tn);
var probs = combs/picks;
document.getElementById('chance').innerHTML = (probs | 0).toLocaleString();

How can I prefix and zeropad a number? [duplicate]

This question already has answers here:
How can I pad a value with leading zeros?
(76 answers)
Closed 8 years ago.
I want a pattern like this:- GT-000001. This pattern gets incremented when a new record is inserted.
So I get values from my DB like this:
var pattern = 'GT-';
var init = 00000;
var recordnumber = 1; // This value i get dynamically.
var result = pattern + init + recodnumber;
But I get result = GT-01. I want result to be GT-000001. How to get this result?
The below example works for recordnumber upto 6 digits. outputing 'GT-000001', 'GT-000012', or 'GT-123456' based on the value of recordnumber
var pattern = 'GT-';
var recordnumber = 1; // This value i get dynamically.
var result = pattern + ('00000' + recordnumber).slice(-6);
console.log(result);
The reason you get that result is that you have
var init = 00000;
Note that the zeroes are not in quotes. That is effectively the same as:
var init = 0;
and so when you put it in the string, you get just the one zero.
If you want five zeroes, you need to use a string:
var init = "00000";
If you're trying to zero-pad, in general, this question and its answers that Matt found may be helpful.
But the short version:
var pattern = 'GT-';
var init = "000000"; // Note there are six of these, not five
var recordnumber = 1; // This value i get dynamically.
var result = String(recordnumber);
result = pattern + init.substring(result.length) + result;
Your init is number type, it is already truncated to 0 on assignment.
You need to add leading zeros manually:
function leadzeros(n, size) {
var s = n+"";
while (s.length < size) s = "0" + s;
return s;
}
var pattern = 'GT';
//var init = 00000; // <- here is 'init' is 0 already, so you can drop it
var recordnumber = 1; // This value i get dynamically.
var result = pattern + leadzeros(recodnumber, 5);

Counting up within a function of Javascript.

I have the following javascript code:
nback.lightElement = function(index) {
var letterArray = new Array('Lorem', 'Ipsum' , 'Dolor', 'Est');
var r = Math.floor(Math.random()*4);
var letter = letterArray[r];
nback.numbers[index] = letter;
nback.numbers.innerHTML = letter;
nback.litCell = letter;
nback.current = letter;
nback.previous.push(nback.current);
};
nback.startGame = function() {
nback.round += 1;
nback.updateRound();
nback.blink_count = 0;
// Make a new game
nback.queue = new Queue();
for (i = 0; i < BLINKS; i++) {
// Populate with random data, less fun than created games
// but this is way easier to program.
nback.queue.queue(Math.floor(Math.random() * 1));
}
// Run the game loop every TIME_BETWEEN_ROUNDS
nback.intervalId = window.setInterval(nback.next, TIME_BETWEEN_BLINKS);
};
This gives my a random word output from the letterArray for TIME_BETWEEN_BLINKS milliseconds (e.g. 1000). That word is shown for 1000ms, disappears, and another word appears randomly. This loops BLINKS-times.
Now I do not want it to choose random words from the letterArray (the var r = Math.floor(Math.random()*4); is one of my main concerns). It should just show them one after another. I tried so many different approches (mainly loops of every kind) but still can't make it work. Most of the time I tried loops I got "undefined" (instead of the actual words) or just nothing (blank).
I use https://github.com/chuckha/N-back as a reference.
Help will be much appreciated.
You can use an index for that array that is initialized outside of the function. Here is some code that gives the next word from the array whenever the lightElement function gets called. It also wraps around.
var letterArrayIndex=0;
nback.lightElement = function(index) {
var letterArray = new Array('Lorem', 'Ipsum' , 'Dolor', 'Est');
var letter = letterArray[letterArrayIndex];
letterArrayIndex = (letterArrayIndex+1) % letterArray.length;
nback.numbers[index] = letter;
nback.numbers.innerHTML = letter;
nback.litCell = letter;
nback.current = letter;
nback.previous.push(nback.current);
};

Categories

Resources