Printing elements of an array - javascript

I'm trying to print the elements of an array. When I try a very basic W3 Schools Example, it works perfectly, but when I take the loops and variables and modify it to my application, it's acting oddly.
Basically, I have a user input. That input is pushed into an empty array. I'm using a loop to cycle through that array and print each element to the screen. If you see the pic, it's not printing correctly. I've tried three different versions of loops and all aren't printing the way I expect.
I instantiate the charNotInWordArr out of the function.
var charNotInWordArr = [];
Relevant JS:
charNotInWordArr.push(userInput);
console.log("the char is not in the word");
console.log("the char is " + userInput)
for (var i = 0; i < charNotInWordArr.length; i++) {
$('#wrongGuessList').append("<li class='list-group-item'>" + userInput[i] + "</li>");
}
Other for loops gone wrong:
$.each(charNotInWordArr, function(userInput) {
$('#wrongGuessList').append("<li class='list-group-item'>" + userInput[i] + "</li>");
});
$.each(charNotInWordArr, function(index, value) {
$('#wrongGuessList').append("<li class='list-group-item'>" + value[i] + "</li>");
});
It's printing like this:

Related

Javascript: for loop not working as expected

Im currently trying to set up a loop that returns exif data from an image using piexifjs.
Up to this point the code provided by the developer of piexif is working correct in my Vue.js environment.
The loop which is used to display the exif-data inside the console looks like this:
for (let ifd in exifObj) {
if (ifd == "thumbnail") {
continue;
}
console.log("-" + ifd);
for (let tag in exifObj[ifd]) {
console.log(" " + piexif.TAGS[ifd][tag]["name"] + ":" + exifObj[ifd][tag]);
}
}
Works fine, but if I try to edit it to return HTML and display the exif information on my Site it just returns one line of information. Here's the code:
for (let ifd in exifObj) {
if (ifd === "thumbnail") {
continue;
}
const exifInfo = $(".modal-exif"),
exifInfoDetail = $(".modal-exif-detail");
exifInfo.html("» " + ifd);
for (let tag in exifObj[ifd]) {
exifInfoDetail.html("<li>" + piexif.TAGS[ifd][tag]["name"] + ":" + exifObj[ifd][tag] + "</li>");
}
}
I guess my loop is overwriting itself where it returns just one value, which, I guess, is fine inside the console since but not inside HTML?
Anyone got any Idea hwo to change the loop to return one line for each entry?
Thank you :)
In the console.log case, each iteration is writing to the console, whereas in the $(selector).html() case, you are overwriting the html content per iteration. The jquery html function states:
Set the HTML contents of each element in the set of matched elements.
That means that each iteration, the html content of $(".modal-exif-detail") is set to one single "<li>" + piexif.TAGS[ifd][tag]["name"] + ":" + exifObj[ifd][tag] + "</li>".
You need to use something like append if you want to continually add to a node, or build up the html string and only execute one html after the loop

How to add up values stored in an array created using push prompt [duplicate]

This question already has answers here:
How to find the sum of an array of numbers
(59 answers)
How to save prompt input into array
(5 answers)
Closed 7 months ago.
I'm prompting the user to enter how many numbers they would like to store in an array. Then I prompt user to enter each individual number and push this into an array, I can display the numbers correctly but now what I'm trying to do is add up all the values. I've searched through the site and there's several solutions but still having problems making my example work. This is the code I have so far.
function howManyValues(userValues) {
for(var i=0;i<userValues;i++) {
myArray=[];
myArray.push(prompt("Enter value postion"+i));
document.write("These are the values you have entered: "+myArray+"<br>");
}
}
var userValues=prompt("How many values do you want to work with: ");
howManyValues(userValues);
Lets start with the mistake in your existing code.
You are re-initialising myArray inside your for loop. This will reset myArray to an empty array on each iteration of the loop. You need to move this variable outside of your loop.
Next, you are using a for loop to prompt the user to enter however many numbers they specify. That's great. It would be more user friendly if the number prompt started at 1, rather than 0.
And finally on to your question. How to sum the values. You're already looping through and capturing the user values as they're entered. The simple solution would be to sum the values as they're entered.
Notice that the captured value is being cast to a Number before summing. This is because prompt will return the value as a String, not a Number.
function howManyValues(count) {
var values = [];
var sum = 0;
for (var i = 1; i <= count; i++) {
var value = prompt('Enter value ' + i);
values.push(value);
sum += Number(value);
document.write('These are the values you have entered: ' + values.join(', ') + '<br>');
}
document.write('The values entered have a sum value of: ' + sum + '<br>');
}
var count = prompt('How many values do you want to work with?');
howManyValues(count);
You are declaring myArray as an empty array at each loop, that needs to be moved outside.
Then to add up, you can use reduce:
myArray.reduce((a, b) => a + b, 0)
So your code should be something like:
function howManyValues(userValues) {
myArray=[];
for(var i=0;i<userValues;i++) {
myArray.push(parseInt(prompt("Enter value postion"+i)));
document.write("These are the values you have entered: " + myArray[i] + "<br>");
}
document.write("The total of the values you have entered: " + myArray.reduce((a, b) => a + b, 0) + "<br>");
}
var userValues=prompt("How many values do you want to work with: ");
howManyValues(userValues);
You can either use a forloop, or reduce for that.
reduce:
myArray.reduce((prev, curr) => prev += curr, 0) // returns 15
for-loop:
let result = 0
for (let i = 0; i < myArray.length; i++) {
result += myArray[i]
}
// result is 15
edit: #fubar's solution suits your code perfectly.
<script>
function howManyValues(userValues) {
let myArray = [];
let sum = 0;
for(let i = 0; i < userValues; i++) {
let newVal = prompt("Enter value postion " + i);
myArray.push(newVal);
sum += parseInt(newVal);
}
document.write("The values you entered are " + myArray.join(', ') + " and their sum is " + sum + "<br>");
}
let userValues=prompt("How many values do you want to work with: ");
howManyValues(userValues);
</script>
Arrays
Objects allow Discord to store keyed collections of values. That’s fine.
But quite often we find Adobe Reader that we need an ordered collection, where we have a 1st, a 2nd, a 3rd element and so on. For example, we need that to store a list of something: users, goods, HTML elements etc.
It is not convenient to use an object here,iTunes because it provides no methods to manage the order of elements. We can’t insert a new property “between” the existing ones. Objects are just not meant for such use.
There exists a special data structure named Array, to store ordered collections.
This was my final answer on this.
function getUserInput(numbers){
userArray=[];
for(var i=1;i<=numbers;i++){
userArray.push(parseInt(prompt("Enter the No. "+i+" value: ")));
document.write(userArray[i-1]+"<br>");
}
document.write("The total for this array is:
"+userArray.reduce((a,b)=>a+b,0));
}
var numbers=prompt("How many numbers do you want to enter: ");
getUserInput(numbers);
You might be interested in array.reduce, which is perfect for transforming an array into a single value, such as a sum. Notice I've transformed input strings into numbers and restructured your code to separate concerns. Error handling is left as an exercise.
const sum = a => a.reduce((a, e) => a + e, 0);
const collectInput = count =>
[...Array(count)].map(() => prompt("Enter a value:"));
const count = +prompt("How many values do you want to work with: ");
const total = sum(collectInput(count).map(Number));
alert("total is: " + total);

Populate a prompt with elements of an array and number them off

(Stack Overflow doesn't have a tag for 'prompt' so I have used alert as I am guessing it is similar enough to attract the right answerers.)
Hello,
I am currently making a JavaScript-based game for an assignment at university. I am usually pretty good with problem solving but have been stumped by this issue.
To explain, I have an array which names the possible armour slots the player can pick. In any order these can be picked, and each time the choice gets pushed to a second array which handles what has already been picked (and in what order) and that item gets spliced from the original array. There is a while loop which runs through until all 3 have been picked.
var armourSlotToPick = ["Head", "Chest", "Legs"],
armourSlotPicked = [],
armourLoop = 1,
indexArmour = 0;
function numInArray() {
indexArmour++;
return (indexArmour + ". " + armourSlotToPick[indexArmour - 1] + "\n");
}
function armour() {
while (armourLoop < 4) {
var armourPick = prompt("Pick an armour slot to generate an item for:\n" + armourSlotToPick.forEach(numInArray));
if (armourPick == 1) {
armourSlotPicked.push(armourSlotToPick[0]);
armourSlotToPick.splice(0,1);
} else if (armourPick == 2) {
armourSlotPicked.push(armourSlotToPick[1]);
armourSlotToPick.splice(1,1);
} else if (armourPick == 3) {
armourSlotPicked.push(armourSlotToPick[2]);
armourSlotToPick.splice(2,1);
} else {
alert("Invalid choice, you suck");
break;
}
armourLoop++;
}
}
I know it probably wouldn't be possible to do the whole return in numInArray() to the prompt, but it shows some working.
Now the problem: I got it working so that each item in the array was numbered (var armourSlotToPick = ["1. Head", "2. Chest", "3. Legs"],) but as you could see, if the player chose 2, then the next time it would show "1. Head (new line) 3. Legs" and when the player chooses 3, a problem would occur, as they were really meant to choose 2. How is it possible to number the items in the array, in a prompt?
I'm possibly over thinking this but I have suffered for a few hours now.
I thank you in advance for any insight you may have,
Daniel.
EDIT: Solved.
Below is the end result, a slight variation from the edited answer from Jonathan Brooks.
var armourSlotToPick = [null, "Head", "Chest", "Legs"]
var armourSlotPicked = [null];
var armourLoop = 1;
function armour() {
while (armourLoop < 4) {
var message = "Pick an armour slot to generate an item for:\n";
for (var i = 0; i < armourSlotToPick.length; i++) {
if (armourSlotToPick[i] !== null) {
message += "" + i + ". " + armourSlotToPick[i] + "\n";
}
}
var armourPick = prompt(message);
if (armourPick > armourSlotToPick.length-1 || armourPick < 1) {
alert("Invalid choice, you suck");
} else {
var insert = armourSlotToPick.splice(armourPick, 1);
armourSlotPicked.push(insert);
}
armourLoop++;
}
armourSlotPicked.splice(0,1);
}
armour();
alert(armourSlotPicked.join("\n"));
I thank all that have contributed to this discussion and the end result, and I hope this is a good example for future problems people may have similar to this.
Check out my fiddle, I think I have a working solution.
What you really want to be using are Object Literals with your own indexing (starting from 1) - if it were me, I would create my own way to iterate over this custom indexing by adding a method to the Object's prototype, but I digress.
You're overcomplicating your code by using a while loop, and that large bulk of if statements is unnecessary: instead, all you need is some basic validation on the input and then you can just trust whatever input passes this validation. That is demonstrated here:
if ( armourPick > armourSlotToPick.length || armourPick < 1 ) {
alert("Invalid choice, you suck");
}
else {
armourSlotPicked.push( armourSlotToPick[armourPick-1] )
alert (armourSlotPicked[armourSlotPicked.length-1].value);
}
Read my code carefully, and you should get a better understanding of how to deal with certain issues.
EDIT:
As per your request, I think I have a solution that suits your needs. Basically all you have to do to have the arrays "start" at an index of 1 is to fill the zeroth element with a null value, like so:
var armourSlotToPick = [null, "Head", "Chest", "Legs"]
var armourSlotPicked = [null];
You just have to remember to take this null object into account in your code, for example:
if (armourSlotToPick[i] !== null) {
message += "" + i + "\n";
}
The indices will update automatically. See this updated fiddle for more details.
use structures / objects as content in the array, instead of just values.
the basic concept:
armourSlotPicked.push({ "key": 1, "value":armourSlotToPick[1]})
alert("value: " + armourSlotPicked[0].value)
alert("key: " + armourSlotPicked[0].key)
edit: responding to comments can take some space.
IMHO a prompt is the completely wrong tool for this, since most browsers would ask the user permission to prevent multiple popups, and since a promt can only return 1 piece of information, you can only ask for 1 thing per popup. Instead you ought to use a div element, with checkboxes for each information..
That being said it can easily be used in a promt.
The prompt is just a built in function, that takes a string as an argument (which is shown as text in the popup) and returns a string with the users input.
what does the magic for you is in fact this:
array.foreach(): The forEach() method executes a provided function once per array element.
in your case that means it calls a function that returns a string for each element in the array, and concatenates the strings.
in the old days you would have written this:
var messageText= "Pick an armour slot to generate an item for:\n"
for(var i = 1; i < armourSlotToPick.length; i++){
messageText += i + ". " + armourSlotToPick[i- 1] + "\n";
}
var armourPick = prompt(messageText);
but in this modern age, you define a printing function, and use it to generate the loop:
function numInArray() {
indexArmour++;
return (indexArmour + ". " + armourSlotToPick[indexArmour - 1] + "\n");
}
//more code before we get to where the function is used....
indexArmour = 0;
var messageText = "Pick an armour slot to generate an item for:\n" + armourSlotToPick.forEach(numInArray);
var armourPick = prompt(messageText);
or in a single line as in your code:
indexArmour = 0; //you forgot this - otherwise the list will only be complete once?
var armourPick = prompt("Pick an armour slot to generate an item for:\n" + armourSlotToPick.forEach(numInArray));
It produces the same output, because it does the same thing, its just written very differently!
If the array holds "object literals" instead of simply values, as I suggest, the old fashioned code would look something like this:
function contains(a, value) {
try{
for (var i = 0; i < a.length; i++) {
if (a[i].value == value) {
return true;
}
}
}
catch(err) {
// do nothing
};
return false;
}
and later..
for(var j = 0; j < 4; j++){
for(var i = 0; i < Math.min(armourSlotToPick.length); i++){
if( contains(armourSlotPicked, armourSlotToPick[i- 1]) )
continue;
var messageText = "Generate an item for armour in slot: " + i + "\n"
messageText += armourSlotToPick[i- 1] + "\n";
}
var armourPick = prompt(messageText);
if (armourPick > 0 && armourPick < armourSlotToPick.length) {
armourSlotPicked.push({"key":j, "value":armourSlotToPick[armourPick]);
}
...
}
//now we have an array that holds information about when what was picked..
or something along those lines.. this is bt.w completely untested, it's just for illustration
You want to use the array index to number your items. Since your numbers are one-based and the index is zero-based, you will need to convert between the two when outputting and interpreting the response.
This approach will also allow you to eliminate all but two of the cases in your if-else statement.

JavaScript splice() not working

for(var i = 0; i < this.phrases.length; i++) {
console.log('sort ' + this.phrases[i]);
console.log('sort length' + this.phrases.length);
if(this.phrases[i] == null) {
var s = this.phrases.splice(i, 1);
console.log('splice ' + this.phrases[i]);
console.log('splice length ' + this.phrases.length);
}
}
I have an array (this.phrases). I made the phrase that I want to remove equal to null in another section. The first log prints null, the second log also prints null. Why is it not getting spliced? This is also sometimes the last item in an array. Are you not able to splice an array with only one element? The same thing happens, however if it is not the last item in this.phrases.
Edit: s also does not seem to get set to any value.
Edit: The two length logs I added print the same number.
Edit: That's not actually true. Weird things are happening with the lengths, probably not involving this section of code. I just want to know if I'm using splice() correctly.
Switch these two lines:
var s = this.phrases.splice(i,1);
console.log('splice ' + this.phrases[i]);
To this:
console.log('splice ' + this.phrases[i]);
this.phrases.splice(i, 1);
i--;
const indexOfValue = treeSelectDataTemp.findIndex((item: any) => item.value === deleteIndexId[d]);
console.log(" ########### deleted indexOfValue ", indexOfValue);
if (indexOfValue !== -1) {
treeSelectDataTemp.splice(indexOfValue, 1);
}

Am I loopy or is it localstorage...?

My goal: To clean up localstorage, by removing previously used items with a for loop.
Usually, I have a number of items, like so:
order-1356666288243 => {"cartID":2713329701836,"productName"...
order-1356666288243 => {"cartID":2713329701836,"productName"...
When I check how many items there are altogether, I get the correct zero-based amount:
console.log( localStorage.length );
Even when I do a for loop to write out the key and values, and console.log() a few other things, all is well:
for(var i=0, len=localStorage.length; i<=len; i++) {
var key = localStorage.key(i);
var value = localStorage[key];
console.log(key + " => " + value);
if(key != '' && key != null){
console.log( key.indexOf('order-') );
console.log(i + '. Key: ', key);
if(key.indexOf('order-') != -1){
console.log('The key to be removed is: ', key.toString());
localStorage.removeItem(key.toString());
}
}
console.log(i + ': ' + len);
}
Everything pretty much does what one would expect. However, this line executes only once when I run the script:
localStorage.removeItem(key);
or
localStorage.removeItem(key.toString());
In fact, I have to run the entire script as many times as there are items. So if I have, say 3 items, I need to run the loop 3 times to get rid of each item.
I'm perplexed: Where did I go wrong? All the console.log() stuff shows up 3 times (if I have 3 items and run the for loop once) . Out of despair, I even changed i < len to i >= len, but that doesn't solve the problem either.
Anyone?
The problem is that you are modifying a collection while you are traversing it. Always be careful when you do this.
In this particular case, the length of localStorage changes when you remove an item, so you end up skipping items.
You should either traverse localStorage backwards (last item to first item), or better yet you should do this in two passes: one pass to collect the keys to remove, and another pass to remove them:
Object.keys(localStorage)
.filter(function(key){return key.indexOf('order-')===0})
.forEach(localStorage.removeItem, localStorage);
Or if you need this to work in IE8 or FF3.x:
var delkeys = [], key, i, len;
for (i=0,len=localStorage.length; i<len, key=localStorage.key(i); i++) {
if (key.indexOf('order-')===0) {
delkeys.push(key);
}
}
for (i=0,len=delkeys.length; i<len, key=delkeys[i], i++) {
localStorage.removeItem(key);
}
I think the problem is that when you remove an item, it changes the length of the local storage. Try iterating from the length-1 down to 0 instead of from 0 up to the length. (By the way, the loop condition should have been i < len, not i <= len. With my suggestion, of course, it should be i >= 0.)
The loop should count down to prevent problems with deleted keys altering storage length. Try this for loop instead:
for( var i = localStorage.length; i--;){
//make sure to remove references to len in your code
}

Categories

Resources