iterating through and changing nodes in singly linked list - javascript

The problem is I don't understand why this code works. It works, but I just can't wrap my mind around it. Here's a function that deletes a node from a singly linked list. I feel like it shouldn't work because it's not actually changing any of the elements in the list, I'm just changing the value of a variable I have set equal to something in the list. In other words, when I create a "runner" variable to iterate through the list, why are the changes I make to "runner" actually changing the list itself. Analogously, if I do
var x = 1
var y = x
y = 2
Obviously, x is still going to equal 1. Why isn't the same true for my Linked List "runner". In the deleteNode function below, why does changing the runner.next value actually change anything in the node or list that exists outside of the function?
function deleteNode(head, position) {
var runner = head
var counter = 0
while (runner) {
if (counter == position - 1) {
runner.next = runner.next.next
return head;
}
runner = runner.next
counter++
}
}

Its because runner is an object, and so the runner variable is a reference to that object.
for example
const x = {a:1}
const y = x;
x.a = 3
console.log(y.a) // this will print 3 also

Related

I am trying to stop my function from displaying the same object twice when clicking a button

I have for quite some time now been trying to figure out how I can stop my code to print the same quote twice.
Also, when every single object in the array has been printed out, I'd like for it to reset somehow. So that you can browse through the quotes once you've gone through all of them.
This is the essential parts of my code:
document.getElementById('loadQuote').addEventListener("click", printQuote, false);
The printQuote function simply contains information that's accessing information from my array:
var randomObjectNumber = getRandomQuote();
var html = "<p class='quote'>"
+ quotes[randomObjectNumber].quote +
"</p>";
document.getElementById('quote-box').innerHTML = html;
One random object is displayed each time you click the eventListener:
function getRandomQuote () {
var randomObjectNumber = Math.floor(Math.random() * quotes.length );
return randomObjectNumber;
}
I have some ideas on how to do this and I have tried them but without success. I tried giving each object a boolean property but I can't really seem to assign each property a boolean value without messing the printQuote function up.
I also tried assigning the object displayed to a different array but the same problem occurred there.
I feel like there is some concepts around the eventListener that I don't fully understand, because every time I try to manipulate a displayed object I just end up changing every single object.
This is what a typical object in the array looks like by the way:
{quote : "Darkness is merely the absence of light"}
(I also have other properties assigned to the object but i feel like presenting them would be redundant)
If someone could explain, or give me a hint, on how to solve this problem I've been struggling with for some time.
Some hints would be greatly appreciated!
Have a nice day.
Sebastian.
EDIT: All code: https://jsfiddle.net/fusqb7hz/
Basically what you need:
Create a separate array that will store all quotes that you've already used.
Remove quote from initial array.
Check if you still have quotes in initial array, if not, get them back from backup array.
The problem is that you call addEventListener twice:
//Let's developers create multiple eventListeners without being redundant.
function onClicking (printFunction) {
document.getElementById('loadQuote').addEventListener("click", printFunction, false);
}
onClicking(printColor);
onClicking(printQuote);
by calling onClicking twice you make the click happen twice, so addEventListener is added twice, meaning one click counts as two.
Change the above code for this:
//Let's developers create multiple eventListeners without being redundant.
document.getElementById('loadQuote').addEventListener("click", function(){
printColor();
printQuote();
});
Here is the jsfiddle:
https://jsfiddle.net/fusqb7hz/3/
I think the easiest approach is to shuffle your quote array and then go through them one by one. This gives you the next "random" as yet unseen quote. The only part I'm not keen on is this shuffler (a derivation of Fisher Yates) modifies the original quote array. You might not care about that though.
// --------------------------------
// A bunch of quotes
// --------------------------------
var quotes = [];
quotes.push({quote : "Darkness is merely the absence of light"});
quotes.push({quote : "quote 2"});
quotes.push({quote : "quote 3"});
quotes.push({quote : "quote 4"});
quotes.push({quote : "quote 5"});
// --------------------------------
// --------------------------------
// Your favorite array shuffle utility
// --------------------------------
var shuffle = function(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
};
// --------------------------------
// --------------------------------
// construct a function to get a random unseen quote until
// all quotes have been seen. Then reset...
// --------------------------------
var getQuote = (function(quotes, shuffle){
var current = 0;
var get = function(){
if ( !quotes || !quotes.length ) { return ""; }
if ( current >= quotes.length ){ current = 0; }
if ( current === 0 ){
console.log("randomizing quotes...");
shuffle(quotes);
}
return quotes[current++].quote;
};
return get;
})(quotes, shuffle);
// --------------------------------
var printQuote = function(){
document.getElementById('quote').innerText = getQuote();
};
document.getElementById('loadQuote').addEventListener("click", printQuote, false);
<div id="quote"></div>
<button id="loadQuote">get quote</button>

How to permanently change var?

So, I have a var set in a function and a array(called "card_idx) set up, and I want the var be set to 0 until a certain number is reached in the array but the number doesn't go up in order (1..2..3..4 extra). It jumps around depending on how the person plays ( so it can be like...1...2...2.1....5....3.2...). And I want the var to be set to 0 until a specific number is reached and then it is changed to 1.
I try having it set up like:
var x=0;
if(card_idx == 3.2){
x=1
}
but the moment there no longer on 3.2 it will change back to zero, how do i make it so it will stay 1?
While your example isn't complete enough to reproduce the problem, I imagine you may be running into trouble with variable scope.
JS variables are locally scoped to the function surrounding them, which works to your advantage here. If you declare x at the beginning of the function that goes through your data, the loop can modify it and the value will be retained after the loop completes:
function crunch(data) {
var x = 0;
data.forEach(function (item) {
if (item.index === 3.2) {
x = 1;
}
});
console.log(x);
}
If any item in data had an index of 3.2, x will be set to 1 and printed to the console at the end. The callback to forEach grabs x using closure, but this would work just the same with a for loop.
Using x within the loop, the value will not be reset until crunch returns. Every time crunch is called, x will be set to 0, may be set to 1 if an item has the right index, and will retain that value until the end of crunch.
Now, with forEach, if you were to declare x inside the loop callback rather than in crunch, it would reset every time:
function crunch(data) {
data.forEach(function (item) {
var x = 0;
if (item.index === 3.2) {
x = 1;
}
});
}
Because var operates at the function level, this will not keep its value and will be 0 for every item.
You could try this. Use an extra boolean to check if x has ever been set.
Be aware that your variables are outside the iteration.
var x = 0;
var hasSet = false;
// start looping
if (card_idx == 3.2 && hasSet = false) {
x = 1
hasSet = true;
}
Or maybe (if your question was more clear) this will work out too.
var x = 0;
// start looping
if (card_idx == 3.2 && x <= 0) {
x = 1
}

Is it Possiable to call to previous increments of a variable?

for example lets say i have a loop that is doing basic counting, while the variable is less than 16 the loop will run and at the end of the loop you add 2 to the variable and add one to a "count" variable
what i want to know is if its possible to callback to any of the previous variables for either variable for example can i count all the times count % 2 === 0?
im not quite sure if once a variable makes any kind of change if all previous versions of that variable are gone
http://codepen.io/anon/pen/Gojoxm
var two = 0;
var count = 0;
while ( two < 16) {
two += 2;
count++;
};
console.log(count);
If I understand you right, then no, you cannot. When you assign a new value to a variable, the previous value is lost.
You have to either run this loop again or store intermediate values in an array:
var values = [];
var two = 0;
while (two < 16) {
two += 2;
values.push(two);
}
console.log(values.length); // the same result
Then, you will always be able to do whatever you want with these values.
For example, you can check if there were any odd values:
var anyOddNumbers = values.some(function(x) { return x % 2 === 1; }); // false

Javascript Object scope

This is a simplification of something that I've come up against in a larger project so I hope it makes sense.
I have two Objects:
FirstObj = {
data : [],
init : function()
{
for(var a = 0; a < 20; a++)
{
this.data[a] = 1;
}
}
};
SecondObj = {
init : function()
{
var cell = FirstObj.data[0];
cell = 0;
}
};
I then call the two init methods and log the results:
(function(){
FirstObj.init();
SecondObj.init();
console.log(FirstObj.data);
})()
Now, I was assuming - based on my basis in Actionscript - that the log would show an Array in which the first item is a 0 and the rest all 1 but the 0 does not seem to stick.
Why does the assignment of the 0 value not succeed here and yet works fine if, instead of cell = 0 I target directly at FirstObj.data[0] = 0.
I'm guessing this is a scope thing and I can work round it but I'm trying to get a proper understanding of how JS actually handles this stuff, especially when lumping code into Objects like this (as an aside, is this a good approach in peoples general opinion?).
Thank for any help.
Numbers in JavaScript are something called primitive value types (alongside strings, booleans null and undefined).
This means, that when you do
var cell = FirstObj.data[0];
You're passing the value in FirstObj.data[0] and not a refernece to it.
What you're doing is like:
var x = 5;
var y = x; // y is now 5
y = 4; // y is 4, x is still 5.
Of course, something like FirstObj.data[0] = 0 should work.
Array indexing returns values in Javascript, not references. It means that once data[0] is assigned to cell, further modification of cell will not affect data[0].
Assigning the array itself would result in the behavior you're looking for:
SecondObj = {
init : function()
{
var cells = FirstObj.data;
cells[0] = 0; // Will also affect data[0].
}
};

Store a table row index as an array index

There a simple function:
selected_row = []; // global scope
function toggleRowNumber(rowIndex) {
if(selected_row[rowIndex]) selected_row.splice(rowIndex, 1);
else selected_row[rowIndex] = 1;
}
usage
toggleRowNumber(50000); // click the row - write the index
toggleRowNumber(50000); // click the row again - remove the inxed
alert(selected_row.length);
50001
OK
Delightful feature!
So is there a way to direct write|read an index without any searchin/looping? And without this huge feat as decribed above.
Thanks.
If I understoold correctly, you want to store and index where you can check/set whether an item is selected or not. If that is the case, you are looking for a "key - value" data structure. Then, why not use a map?
var selected_row = {};
function toggleRowNumber(rowIndex) {
if(selected_row[rowIndex]) selected_row[rowIndex] = 0; //or = undefined;
else selected_row[rowIndex] = 1;
}
That is better because hash map will save you time and space.
Space becuase you are not storing hundreds of 'undefined' values in a vector.
Time because, hash function used to access elements is pretended to hit the right position in many cases.

Categories