I have a nested loop that will work most of the time, but for one particular case it does not run at all.
Here is the value that is failing: 1, 3-5, 7-10, 22
JS code:
document.getElementById("myButton").addEventListener("click", function () {
document.getElementById("msg").innerHTML = "";
// Get the short list
var list = document.getElementById("myIn").value;
var sublists = list.split(", ");
var Range = [];
var result = "";
var start; // for the nested loop
var end; // for the nested loop
for (var i = 0; i < sublists.length; i++) {
Range = sublists[i].split("-");
start = Range[0];
end = Range[Range.length-1];
Log("Range: " + Range); // Shows which parts of the sublist the program sees
for (var j = start; j <= end; j++) {
result = result + j + ",";
Log("Result in loop: " + result); // Show which parts make it inside the loop
}
}
result = result.slice(0, -1); // Takes off the extra comma at the end
Log("Result: " + result); // Shows result
});
When the failing value is entered, this is the result:
Range: 1
Result in loop: 1,
Range: 3,5
Result in loop: 1,3,
Result in loop: 1,3,4,
Result in loop: 1,3,4,5,
Range: 7,10 <--- Never goes inside the loop
Range: 22
Result in loop: 1,3,4,5,22,
Result: 1,3,4,5,22
I can't figure out why the 7-10 part is being skipped. Any help or explanation is greatly appreciated.
Here is the FIDDLE
You need use parseInt when work with integer here
start = parseInt(Range[0],10);
end = parseInt(Range[Range.length-1],10);
After splittng you get array with strings, and when you try compare "7" with "10" it compared as string and "7" always greater then "10", because char code for '7' greater than char code for '1' (first char in "10")
For converting to number you can use next function also: Number, parseInt or parseFloat
document.getElementById("myButton").addEventListener("click", function() {
document.getElementById("msg").innerHTML = "";
// Get the short list
var list = document.getElementById("myIn").value;
var sublists = list.split(", ");
var Range = [];
var result = "";
var start; // for the nested loop
var end; // for the nested loop
for (var i = 0; i < sublists.length; i++) {
Range = sublists[i].split("-");
start = parseInt(Range[0], 10);
end = parseInt(Range[Range.length - 1], 10);
Log("Range: " + Range); // Shows which parts of the sublist the program sees
for (var j = start; j <= end; j++) {
result = result + j + ",";
Log("Result in loop: " + result); // Show which parts make it inside the loop
}
}
result = result.slice(0, -1); // Takes off the extra comma at the end
Log("Result: " + result); // Shows result
});
// Log is my imitation of console.log()
function Log(stuff) {
var msg = document.getElementById("msg");
var newDiv = document.createElement("div");
newDiv.innerHTML = stuff;
msg.appendChild(newDiv);
}
<p>Try this value in the input: 1, 3-5, 7-10, 22</p>
<input id="myIn" type="text" />
<button id="myButton" type="button">Go</button>
<p id="msg"></p>
Since you are using a text input field all values from that field are strings. Then you use string manipulations that return more string values. You are never dealing with numbers. So Javascript will treat them as string values when testing if one value is greater than the other.
You can use the Number global object to safely cast a string value to a number. The benefit of Number over parseInt and parseFloat is if any part of the string is non numeric it will return a NaN value whereas the other two will return as much of the string as a number up to the first non-numeric character.
start = Number(Range[0]);
Related
Im new to Javascript and i cant figure out how to make this work. I have to use an array. I can only get it to show one of the numbers in the browser.
it prints:
Even Number = 20
I need it to print:
Odd Number = 1
Even Number = 2
Odd Number = 3
Even Number = 4
Odd Number = 5
Even Number = 6
Odd Number = 7
Even Number = 8
Odd Number = 9
Even Number = 10
Odd Number = 11
Even Number = 12
Odd Number = 13
Even Number = 14
Odd Number = 15
Even Number = 16
Odd Number = 17
Even Number = 18
Odd Number = 19
Even Number = 20
Here is what I have. Any help would be appreciated.
<script>
var numbers = [];
for (var i=1; i<=20; i++){
numbers.push(i);
if (i % 2 === 0){
document.getElementById("demo").innerHTML ="Even Number = "+i;
}
else {
document.getElementById("demo").innerHTML ="Odd Number = "+i;
}
}
</script>
That is because when you are doing document.getElementById("demo").innerHTML it is overwriting the previous content. Instead during each iteration create a div element and then append that as child of div#demo
var numbers = [];
for (var i = 1; i <= 20; i++) {
numbers.push(i);
let createElem = document.createElement('div');
let creatTxtNode;
if (i % 2 === 0) {
createTxtNode = document.createTextNode("Even Number = " + i);
} else {
createTxtNode = document.createTextNode("Odd Number = " + i);
}
createElem.appendChild(createTxtNode)
document.getElementById("demo").appendChild(createElem);
}
<div id='demo'></div>
Since you are assigning (=) the new value to the element, in each iteration the previous values are removed. You can either use += to concatenate the new value with the previous value OR try with insertAdjacentHTML():
var numbers = [];
var targetEl = document.getElementById("demo")
for (var i=1; i<=20; i++){
numbers.push(i);
if (i % 2 === 0){
targetEl.insertAdjacentHTML('beforeend', "Even Number = "+i + "<br>");
}
else {
targetEl.insertAdjacentHTML('beforeend', "Odd Number = "+i+ "<br>");
}
}
<div id="demo"><div>
You're on the right path with your solution. Just replace innerHTML = ... with innerHTML += ....
That will do the trick for you since with each iteration innerHTML operation is replacing your existing content, you actually need to append it.
var numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20];
var copyNumbers = [];
var targetEl = document.getElementById("getNumbers")
numbers.forEach(function(i) {
copyNumbers.push(i);
switch (i % 2) {
case 0:
getNumbers.innerHTML += ("Even Number = <b><i>" + i + "</i></b><br />");
break;
default:
getNumbers.innerHTML += ("Odd Number = <b><i>" + i + "</i></b><br />");
}
});
<div id='getNumbers'></div>
Note:- you need to replace innerHTML = ... with innerHTML += .... each iteration instead of replacing your existing content, you need to append it.
<html>
<body>
<div id="demo"></div>
</body>
<script>
function evenOdd() {
//Create an array of even odd numbers result
evenOddArray = [...Array(20).keys()].map(x => {
if((x+1)%2==0){
return "Even Number = " + (x+1)
}
return "Odd Number = " + (x+1)
})
//loop through each result
evenOddArray.forEach(x => {
var t = document.createTextNode(x);// Create a text node
var br = document.createElement("br") // Create a new line node
document.getElementById("demo").appendChild(t) //append to demo
document.getElementById("demo").appendChild(br)
})
}
evenOdd()
</script>
</html>
https://jsfiddle.net/zpcu5mb8/
There are two key things.
First, as the others have noted, your use of innerHTML simply replaces the content each time which is why you're only getting the last output from the loop.
Second: "I have to use an array."
While you're pushing numbers to your array in your example ultimately it's pointless - you add numbers to it but don't use the array in any way. If it's a requirement for your work, you might get marked down for that.
So here's an example that fixes both issues:
1) It creates an array of numbers
2) It loops over that array of numbers and produces the output
// First we create out numbers array...
const numbers = [];
// ...and fill it with numbers
for (let i = 1; i <= 20; i++) {
numbers.push(i);
}
// We create an output array to store our strings
// You could concatenate the strings in the loop with `+=`
// but building an array and joining it up later is a little cleaner
const output = [];
// Now: loop over the numbers array
for (let i = 0; i < numbers.length; i++) {
// Grab the number. We want to check whether that
// is even/odd instead of the index
const number = numbers[i];
// Our condition: we push a different string to the array
// depending on whether its even/odd. I've used template literals
// as they're cleaner solution to using string concatenation
if (number % 2 === 0) {
output.push(`Even number = ${number}`);
} else {
output.push(`Odd number = ${number}`);
}
}
// Finally we grab our element
const demo = document.querySelector('#demo');
// And we add the joined up array to it
demo.insertAdjacentHTML('beforeend', output.join('<br/>'));
<div id="demo"></div>
Further reading
insertAdjacentHTML
Template literals
I have a function that I have modified to get a string (which consists of zeros and ones only).
The string (timesheetcoldata):
100000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000
The string items (the numbers one and zero) will change every time the function is run.
It will always be the same length.
I have made the string above easier to see what I am trying to achieve.
I want to return the first character and then every 24th character (as in the variable colsCount in the function).
so, in the example above, it would return something like: 111111
I then want to convert these characters to numbers (something like [1, 1, 1, 1, 1, 1]).
I then want to sum these number together (so it would return, in the example: 6).
I then want to check if the returned number matches the variable: rowsCount
or true if it does, false if it does not.
My function:
$("#J_timingSubmit").click(function(ev){
var sheetStates = sheet.getSheetStates();
var rowsCount = 6;
var colsCount = 24;
var timesheetrowsdata = "";
var timesheetcoldata = "";
for(var row= 0, rowStates=[]; row<rowsCount; ++row){
rowStates = sheetStates[row];
timesheetrowsdata += rowStates+(row==rowsCount-1?'':',');
}
timesheetcoldata = timesheetrowsdata.replace(/,/g, '');
console.log(timesheetcoldata);
});
Thank you very much to both Rajesh and MauriceNino (and all other contributers).
With their code I was able to come up with the following working function:
$("#J_timingSubmit").click(function(ev){
var sheetStates = sheet.getSheetStates();
var rowsCount = 6;
var timesheetrowsdata = "";
var timesheetcoldata = "";
for(var row= 0, rowStates=[]; row<rowsCount; ++row){
rowStates = sheetStates[row];
timesheetrowsdata += rowStates+(row==rowsCount-1?'':',');
}
timesheetcoldata = timesheetrowsdata.replace(/,/g, '');
var count = 0;
var list = [];
for(var i = 0; i< timesheetcoldata.length; i+=24) {
const num1 = Number(timesheetcoldata.charAt(i));
list.push(num1);
count += num1;
}
let isSameAsRowsCount = count == rowsCount;
console.log('Is Same? ', isSameAsRowsCount);
});
You can always rely on traditional for for such action. Using functional operations can be more readable but will be more time consuming(though not by much).
You can try this simple algo:
Create a list that will hold all numbers and a count variable to hold sum.
Loop over string. As string is fixed, you can set the increment factor to the count(24).
Convert the character at given index and save it in a variable.
Push this variable in list and also compute sum at every interval.
At the end of this loop, you have both values.
var string = '100000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000';
var count = 0;
var list = [];
for(var i = 0; i< string.length; i+=24) {
const num1 = Number(string.charAt(i));
list.push(num1);
count += num1;
}
console.log(list, count)
Here is a step by step explanation, on what to do.
Use match() to get every nth char
Use map() to convert your array elements
Use reduce() to sum your array elements
Everything needed to say is included in code comments:
const testData = '100000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000';
// Step 1) Create array of numbers from string
const dataArr = testData.match(/.{1,24}/g) // Split on every 24th char
.map(s => Number(s[0])) // Only take the first char as a Number
console.log(dataArr);
// Step 2) Sum array Numbers
let dataSum = dataArr.reduce((a, b) => a + b); // Add up all numbers
console.log(dataSum);
// Step 3) Compare your variables
let rowsCount = 123; // Your Test variable
let isSameAsRowsCount = dataSum == rowsCount;
console.log('Is Same? ', isSameAsRowsCount);
As #Jaromanda mentioned, you can use the following to done this.
const string = '100000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000100000000000000000000000';
const value = string.split('').filter((e,i)=> !(i%24)).reduce((acc,cur)=> acc+ (+cur), 0);
console.log(value);
I'm trying to take a string with blank spaces and display each word line-by-line in console output.
My javascript code takes a string and creates an array of indexes where spaces are identified using an indexOf() operation. This is then passed through a slice loop which subtracts the different indexes to get a length of the string to slice and the space index to locate it in the existing string. The output is the final console.log and it appears to do what I need it to even when passing in random strings.
var sp = " ";
var myStr = "I am a \"double quoted\" string inside \"double quotes\""
var twoStr = 'I am a string "and I am a string"';
var stringadd = "and I can slice whenever I want."
var threeStr = myStr + sp + twoStr;
var fourStr = threeStr + sp + stringadd;
console.log("string length = ", fourStr.length);
var i = 0;
var n = 0;
var sentence = [i];
for (n = 0; n < fourStr.length; n++) {
var pos = fourStr.indexOf(sp, n) //find the index of the space
if (n == pos) {
sentence[i] = pos; //place the index in an array
i++;
} else(i);
}
var arraysent = fourStr.split(sp); //test split function for string
console.log("Array Sentence:\n", arraysent)
console.log("space index length:\n", sentence.length) //check array length
console.log("space index array:\n", sentence) //display array with "space" indexes
console.log("sliced string:\n", fourStr.slice(sentence[0] - 1, sentence[0])); //display first index
var j = 0;
for (j = 0; j < sentence.length; j++) {
var slicesent = fourStr.slice(sentence[j], sentence[j + 1]); //automate remaining index display
console.log(slicesent);
}
I was hoping to find an easier/simpler way to do this same task since passing the string to the array is not efficient and re-creates the string a bunch of times. Could someone please explain a better alternative that will show the individual words of a string line-by-line in the console?
Thank you
This is literally done by String.split()
function logWordsBySpaces(str){
let arr = str.split(" ");
arr.forEach(function(a){ console.log(a); })
}
logWordsBySpaces("Karma karma karma karma karma chameleon!")
You should use .split
var sp = " ";
var myStr = "I am a \"double quoted\" string inside \"double quotes\""
var twoStr = 'I am a string "and I am a string"';
var stringadd = "and I can slice whenever I want."
var threeStr = myStr + sp + twoStr;
var fourStr = threeStr + sp + stringadd;
const result = [myStr, twoStr, stringadd, threeStr, fourStr].map(string => string.split(sp));
console.log(result);
Ok so I am trying to access each individual number in the strings inside of this array.
var array = ['818-625-9945','999-992-1313','888-222-2222','999-123-1245'];
var str = "";
for (i=0; i<array.length; i++) {
str = array[i];
}
The problem is that this is the output: '999-992-1313'
and not the first element array[0]: '818-625-9945'
When I try doing a nested for loop to go through each element inside the string I am having trouble stating those elements.
var array = ['818-625-9945','999-992-1313','888-222-2222','999-123-1245'];
for (i=0; i<array.length; i++) {
for (j=0; j<array[i].length; j++) {
console.log(array[i][j]);
}
}
I do not know how to access each individual number inside of the string array[i]. I would like to find a way to make a counter such that if I encounter the number '8' I add 8 to the total score, so I can take the sum of each individual string element and see which number has the highest sum.
var array = ['818-625-9945','999-992-1313','888-222-2222','999-123-1245'];
for (i=0; i<array.length; i++) {
for (j=0; j<array[i].length; j++) {
if (array[i](j).indexOf('8') !== -1) {
// add one to total score
// then find a way to increase the index to the next index (might need help here also please)
}
}
}
Mabe this works for you. It utilized Array.prototype.reduce(), Array.prototype.map() and String.prototype.split().
This proposal literates through the given array and splits every string and then filter the gotten array with a check for '8'. The returned array is taken as count and added to the return value from the former iteration of reduce - and returned.
var array = ['818-625-9945', '999-992-1313', '888-222-2222', '999-123-1245'],
score = array.reduce(function (r, a) {
return r + a.split('').filter(function (b) { return b === '8'; }).length;
}, 0);
document.write('Score: ' + score);
A suggested approach with counting all '8' on every string:
var array = ['818-625-9945', '999-992-1313', '888-222-2222', '999-123-1245'],
score = array.map(function (a) {
return a.split('').filter(function (b) { return b === '8'; }).length;
});
document.write('Score: ' + score);
Actually rereading your question gave me a better idea of what you want. You simply want to count and retrieve the number of 8's per string and which index in your array conforms with this maximum 8 value. This function retrieves the index where the value was found in the array, how many times 8 was found and what is the string value for this result. (or returns an empty object in case you give in an empty array)
This you could easily do with:
'use strict';
var array = ['818-625-9945', '999-992-1313', '888-222-2222', '999-123-1245'];
function getHighestEightCountFromArray(arr) {
var max = 0,
result = {};
if (arr && arr.forEach) {
arr.forEach(function(value, idx) {
var cnt = value.split('8').length;
if (max < cnt) {
// found more nr 8 in this section (nl: cnt - 1)
max = cnt;
// store the value that gave this max
result = {
count: cnt - 1,
value: value,
index: idx
};
}
});
}
return result;
}
console.log(getHighestEightCountFromArray(array));
The only thing here is that when an equal amount of counts is found, it will still use the first one found, here you could decide which "maximum"
should be preferred(first one in the array, or the newest / latest one in the array)
OLD
I'm not sure which sums you are missing, but you could do it in the following way.
There I first loop over all the items in the array, then I use the String.prototype.split function to split the single array items into an array which would then contain ['818', '625', '9945']. Then for each value you can repeat the same style, nl: Split the value you are receiving and then loop over all single values. Those then get convert to a number by using Number.parseInt an then all the values are counted together.
There are definitelly shorter ways, but this is a way how you could do it
'use strict';
var array = ['818-625-9945','999-992-1313','888-222-2222','999-123-1245'],
sumPerIndex = [],
totalSum = 0;
array.forEach(function(item, idx) {
var values = item.split('-'), subArray = [], itemSum = 0;
values.forEach(function(value) {
var singleItems = value.split(''),
charSum = 0;
singleItems.forEach(function(char) {
charSum += parseInt(char);
});
itemSum += charSum;
subArray.push(charSum);
console.log('Sum for chars of ' + value + ' = ' + charSum);
});
sumPerIndex.push(subArray);
totalSum += itemSum;
console.log('Sum for single values of ' + item + ' = ' + itemSum);
});
console.log('Total sum of all elements: ' + totalSum);
console.log('All invidual sums', sumPerIndex);
My friend asked me to help him with homework, and I'm stuck. Here is assignment:
user must enter in first prompt box number of elements in array. Then, he will get prompt box for each number to enter. Now, output must be greatest number in array. But that simply doesn't work. With my code below, I always get the element who has greatest first digit. (it's doesn't matter if number is negative or positive, code doesn't work as it should)
Here is my code (it even doesn't work in jsfiddle, just in my file)
<button onclick="duzinaNiza()">Do it!</button>
and here is JavaScript
function duzinaNiza() {
var brClanova = prompt("Enter the number of array elements:");
if (brClanova > 0) {
var niz = new Array();
for (i=0; i<brClanova; i++) {
var redniBr = i+1;
niz[i] = prompt("Enter "+ redniBr +". array number:");
\\ prompt for geting each array element
}
var maximum = niz[0];
for (a=0; a<brClanova; a++) {
if (maximum < niz[a]) {
maximum = niz[a];
}
}
document.write("Greatest value in array is: " + maximum);
}
}
My friend's proffesor doesn't want to use functions for sorting arrays, this must be done with loops.
P.S. Yeah, I know... But don't ask about document.write thing, it must be printed in that way...
That is because the input is a String, you have to parse it to a Integer. Like:
niz[i] = parseInt(prompt("Enter "+ redniBr +". array number:"), 10);
Try this:
function duzinaNiza() {
var brClanova = prompt("Enter the number of array elements:");
if (brClanova > 0) {
var niz = new Array();
for (i=0; i<brClanova; i++) {
var redniBr = i+1;
niz[i] = parseInt(prompt("Enter "+ redniBr +". array number:"));
// prompt for geting each array element
}
var maximum = niz[0];
for (a=0; a<brClanova; a++) {
if (maximum < niz[a]) {
maximum = niz[a];
}
}
document.write("Greatest value in array is: " + maximum);
}
}
The problem is that you are comparing two strings, when you wanted to compare two numbers.
In other words, the following expression is LEGAL in javascript and evaluates to true:
if('4' > '393939393'){
//true! string '4' is greater than string '3' (first char of '393939393')
}
What you should do is cast the value received from the function prompt, so it is treated as a number. You can do that using the following function:
parseInt(prompt("Enter "+ redniBr +". array number:"), 10);
The first parameter is the value you want to cast to a number, while the second is the radix (or "base") of the number.
So, the main problem here is that you're not threat your numbers as "number", but as string. The method prompt returns a string, so you need to convert them:
function duzinaNiza() {
var brClanova = +prompt("Enter the number of array elements:");
if (!brClanova)
return;
var niz = [];
for (var i=0; i < brClanova; i++) {
var redniBr = i + 1;
niz[i] = +prompt("Enter "+ redniBr + ". array number:");
}
var max = niz[0];
for (var a = 1; a < brClanova; a++) {
if (max < niz[a])
max = niz[a];
}
document.write("Greatest value in array is: " + max);
}
I used the Unary Plus Operator for that.
Just for to know, in JS you can actually avoid the last loop using Math.max to get the maximum of an array of numbers. So instead of:
var max = niz[0];
for (var a = 1; a < brClanova; a++) {
if (max < niz[a])
max = niz[a];
}
document.write("Greatest value in array is: " + max);
You will have:
var max = Math.max.apply(null, niz);
document.write("Greatest value in array is: " + max);
In that case, you don't even need the unary plus operator because Math.max takes care of that.
try this out, [Tip: i just utilised the '+' operator for casting the value to number (values from prompt.). The '+' operator will return NaN, if the entered value could not get converted into a number. so in that situation, you should use isNan function to get rid of that.]
duzinaNiza = function () {
var brClanova = prompt("Enter the number of array elements:");
if (brClanova > 0) {
var niz = new Array();
var maximum;
for (i=0; i<brClanova; i++) {
var temp = +prompt("Enter "+ i+1 +". number:");
if(i===0) { maximum = temp }
else { maximum = (temp > maximum)?temp:maximum; }
}
alert("Greatest value in array is: " + maximum);
}
}
You don't need parseInt- if you subtract strings that can be converted to numbers, they are converted. So you can subtract the maximum from the next number, and see if it leaves a remainder.
Also, parseInt will destroy decimals, so you won't know that 1.5 is greater than 1.
Your comment used the wrong characters- `('\' should be '//')
function duzinaNiza(){
var brClanova= prompt("Enter the number of array elements:");
if(brClanova>0){
var niz= new Array();
for(var i= 0;i<brClanova;i++){
var redniBr= i+1;
niz[i]= prompt("Enter "+ redniBr +". array number:");
//prompt for geting each array element
}
var maximum= niz[0];
for(var a= 0;a<brClanova;a++){
if(niz[a]-maximum>0){
maximum= niz[a];
}
}
document.write("Greatest value in array is: " + maximum);
}
}
Modified Code JSFIDDLE
function duzinaNiza() {
var brClanova = prompt("Enter the number of array elements:")*1; //convert string to intger
if (brClanova > 0) {
var niz = new Array();
for (i=0; i<brClanova; i++) {
var redniBr = i+1;
niz[i] = prompt("Enter "+ redniBr +". array number:")*1;
// prompt for geting each array element
}
var maximum = niz[0];
for (a=0; a<brClanova; a++) {
if (maximum < niz[a]) {
maximum = niz[a];
}
}
document.write("Greatest value in array is: " + maximum);
}
}