Confusion understanding closures - javascript

Conceptually closures make a bit of sense to what's happening, but in practice, I have no idea what's going on. For the problem I am dealing with I want to count the occurrences of numbers I read in and store it in a histogram. This is supposed to happen in the countOccurences function, but the histogram array never gets updated.
var LinkedList = function() {
this.head = null;
}
LinkedList.prototype.add = function(val) {
this.head = {data: val, next: this.head};
};
LinkedList.prototype.forEach = function(action) {
for (var temp = this.head; temp; temp = temp.next) {
action(temp.data);
}
};
// This is where the closure concept should take effect
var countOccurrences = function(histogram) {
return function(val){ // Not working as expected, The val should equal
// a number found in the list. Take for example if
// 1 is found then histogram[1]++. Meaning we've
// seen the number 1 once in the list so far. This
// continues until the entire list has been processed.
histogram[val]++;
};
}
function printHistogram(histogram) {
for (var i in histogram) {
if (histogram[i]) {
println("(#" + i + ":" + histogram[i] +")")
}
}
}
var main = function() {
var list = new LinkedList(); //Creates empty linkedlist
var histogram = [];
while (ln = readln().trim()) { //Reads in numbers from stdin
list.add(ln)
}
list.forEach(countOccurrences(histogram))
printHistogram(histogram)
}; main()

The actual closure was going wrong because of the lack of a return statement initially. However, after that, I found another bug that was unrelated to closure. The problem was in the function because I was incrementing a number that wasn't initialized. So the fix is as follows:
var countOccurrences = function(histogram) {
return function(val) {
if(histogram[val])
histogram[val]++;
else
histogram[val] = 1;
};
}
Regardless, much apperciation for the help.

Your closure is not actually returning a function. Not exactly sure how you are counting or what those values will be but you definitely need to start by returning your function from your closure.
var LinkedList = function() {
this.head = null;
}
LinkedList.prototype.add = function(val) {
this.head = {
data: val,
next: this.head
};
};
LinkedList.prototype.forEach = function(action) {
for (var temp = this.head; temp; temp = temp.next) {
action(temp.data);
}
};
// This is where the closure concept should take effect
var countOccurrences = function(histogram) {
return function(val) { // Not working as expected, I'm tring to get val to
// be the data passed in from forEach which will
// then be incremeted accordingly in the histogram
// array
histogram[val] = histogram[val] ? histogram[val] + 1 : 1;
};
}
function printHistogram(histogram) {
for (var i in histogram) {
if (histogram[i]) {
println("(#" + i + ":" + histogram[i] + ")")
}
}
}
var main = function() {
var list = new LinkedList(); //Creates empty linkedlist
var histogram = [];
while (ln = readln().trim()) { //Reads in numbers from stdin
list.add(ln)
}
list.forEach(countOccurrences(histogram))
printHistogram(histogram)
};
main()

Related

Javascript: making functions at runtime

update
solution works in foreach loop but not in for loop
function x(number){
return number - 10;
}
var i = 0
var runtimefunctions = {};
var allLevels = {"1":"State","2":"Educational_Services","3":"Principal_Networks","4":"Schools"}
for (var key in allLevels) {
runtimefunctions[i] = function() { return x(i); };
i++;
};
console.log(runtimefunctions[1]()); // -6
console.log(runtimefunctions[2]()); // -6
console.log(runtimefunctions[3]()); // -6
tried hard to make functions but it's first time to create such thing so cant understand the proper way...
I have a function..
function x(number){
return number - 10;
}
runtimefunctions = {};
now I have a loop to run
[1,2,3].forEach(function(y){
//here I want to create a function.. which will make a function x(y) -- like this
runtimefunctions[x] = new Function("return function x_" + levelIterator + "(levelIterator){ console.log(levelIterator); x(" + y + ") }")();
});
so basically..want to make functions like this.
runtimefunctions= {
"1": x(1),
"2": x(2),
and so on
}
Is this what you need?
function x(number){
return number - 10;
}
var runtimefunctions = {};
[1,2,3].forEach(function(y){
runtimefunctions[y] = function() { return x(y); };
});
console.log(runtimefunctions[1]()); // -9
console.log(runtimefunctions[2]()); // -8
console.log(runtimefunctions[3]()); // -7
To satisfy your next (for-in) requirement, you need to closure the index variable with additional function call:
var runtimefunctions = {}, i = 0;
var allLevels = {"1":"State","2":"Educational_Services","3":"Principal_Networks","4":"Schools"}
for (var key in allLevels) {
runtimefunctions[i] = function(index){ return function() { return x(index); } }(i++);
};
It is much easier.
For example:
const createFunctionWith = (x) => {
return (param) => console.log(x, param)
}
let a = [1,2,3].map(x => createFunctionWith(x));
console.log(a[1]("bebe")); // 2, "bebe"
https://jsfiddle.net/muLxoxLd/
You could do something like this
// Found in your code
var x = (a) => {
console.log(a)
};
var runtimefunctions = {};
[1, 2, 3].forEach(function(y) {
//Create a function with a parameter named "levelIterator"
runtimefunctions[y] = Function("levelIterator", "{ console.log(levelIterator); x(" + y + ") }");
});
runtimefunctions[1]('test')

ng-repeat in linked data object

I have a Node object inside my Angular controller. Each Node has a next property which points to the next item:
$scope.Stack = function () {
this.top = null;
this.rear = null;
this.size = 0;
this.max_size = 15;
};
$scope.Node = function (data) {
this.data = data;
this.next = null;
this.previous = null;
};
$scope.Stack.prototype.pushUp = function (data) {
for (i = 0; i < data.items.length; i++) {
if (data.items[i]) {
var node = new $scope.Node(data.items[i]);
if (node) {
node.previous = this.top;
if (this.top) {
this.top.next = node;
}
this.top = node;
// if first push, the set the rear
if (this.size == 0) {
this.rear = node;
}
this.size += 1;
}
}
}
};
Creating object:
$scope.Timeline = new $scope.Stack();
My question: is there a way to iterate over linked data structures like this using ng-repeat/Angular?
According to the AngularJS docs,
variable in expression – where variable is the user defined loop variable and expression is a scope expression giving the collection to enumerate.
therefore ngRepeat can only be used to iterate over a Javascript "Collection". Collections include Arrays, Maps, Sets, and WeakMaps. So the answer to your question is No, you cannot iterate over a linked structure.

How to make a function that contains a promise return a value instead of a promise?

Say, I have a function F1 that will be called in many other function. F1 is meant to return a value VAL that will be used in F2. A promise is needed to retrieve that needed data that will help calculate VAL. Having F1 as a promise would cause a lot of confusion in F2, for F1 is often called inside IF statements and FOR loops. Let me illustrate this scenario:
function F1(param1, param2) {
var VAL = 0;
promise(param1, param2).then(function(data) {
for (var i = 0; i < data.length; i++) {
// Do some calculation here
}
});
return VAL;
}
function F2(x1, x2) {
var myArray = [],
someValue = 0;
if ([conditional expression]) {
someValue = F1(x1, x2);
call_some_function();
myArray.push({
val: someValue,
...
});
}
var x = someValue + y;
myArray.push({
id: x,
...
});
return myArray;
}
How do I make sure that F1 returns VAL (integer) so I can use it as a synchronous function?
Thanks in advance for your help.
EDIT:
Here is how the code looks like:
function myFunc(x, y) {
return init()
.then(function() {
return getData(x, y).then(function(data) {
if (data.length == 0) return [];
var id, name,
firstPass = true,
headIn = 0,
headOut = 0,
currentHead = 0,
payWtIn = 0,
payWtOut = 0,
expectedAdg = 0,
weight = 0,
results = [];
for (var i = 0; i < data.length; i++) {
if (firstPass) {
id = data[i].id();
name = data[i].name();
headIn = data[i].headIn();
headOut = data[i].headOut();
expectedAdg = data[i].expectedAdg();
firstPass = false;
}
if (id != data[i].id()) {
buildFunc();
reset();
}
headIn += data[i].headIn();
headOut += data[i].headOut();
payWtIn += data[i].payWtIn();
payWtOut += data[i].payWtOut();
}
buildFunc();
return results;
function buildFunc() {
currentHead = headIn - headOut;
var headDays = getHeadDays({ locationId: locationId, groupId: groupId, callDate: null });
var totalWeight = headIn != 0
? ((((headDays * expectedAdg) + payWtIn) / headIn) * currentHead) + payWtOut
: 0;
results.push({
id: id,
name: name,
headIn: headIn,
headOut: headOut,
headDays: headDays,
currentHd: currentHead,
totalWt: totalWeight
});
}
function reset() {
id = data[i].id();
name = data[i].name();
headIn = data[i].headIn();
headOut = data[i].headOut();
expectedAdg = data[i].expectedAdg();
payWtIn = 0;
payWtOut = 0;
weight = 0;
}
});
});
}
function getHeadDays(params) {
var VAL = 0;
promise(params.a, params.b).then(function(data) {
for (var i = 0; i < data.length; i++) {
// Make calculation to determine VAL here
}
});
return VAL;
}
The init function loads needed entities in the cache (I'm working with BreezeJs) for querying. The getData function gets raw data that are sorted by id from database, and those data are used to determine the results array. As the data are looped through, as long as the id of each record is the same, headIn, headOut, payWtIn and payWtOut are incremented by the record fields, and when the previous and current id are different, we can calculate totalWeight and push a new record to the results array with the buildFunc function. Inside that buildFunc function, we retrieve the headDays in order to calculate totalWeight. The getHeadDays function will be called in many other functions. Please, let me know if you have any questions. Thanks in advance for your help.
You can't.
If you need to return a promise, then that is because the value won't be available until some event happens, and the function will (or at least may) return before then. That's the point of promises.

Nest JSON from array

I am trying to achieve something which seemed very basic but is getting me mad over the last days.
I have a simple array : ["a","b","c","d","e"] and I want to turn it into a nested JSON like this:
{"a":{"b":{"c":{"d":{"e":""}}}}}
Looping over it, I ran in problems like "how do you save the last key to set it afterwards without erasing it" and so on.
Does anyone has an idea?
You might have had problems because you were looping in the wrong direction. Try to build the object from inside-out:
array.reduceRight(function(v, key) {
var o = {};
o[key] = v;
return o;
}, "")
or, with a loop:
var val = "";
for (var i=array.length; i--; )
var o = {};
o[array[i]] = val;
val = o;
}
return val;
Here's one way to do it, recursively:
function convertToNestedObject(arr) {
var result = {};
if (arr.length === 1) {
result[arr[0]] = '';
} else {
result[arr[0]] = convertToNestedObject(arr.slice(1, arr.length));
}
return result;
}
You could pass the start index in to the function instead of using slice and creating copies of the array:
function convertToNestedObject(arr, startIndex) {
var result = {};
if (arr.length - startIndex === 1) {
result[arr[startIndex]] = '';
} else {
result[arr[startIndex]] = convertToNestedObject(arr, startIndex + 1);
}
return result;
}
Example: http://jsfiddle.net/jwcxfaeb/1/
Put current element as key and empty object ({}) as value. Continue with newly inserted empty object.
function toNested(arr){
var nested = {};
var temp = nested;
for(var i=0; i<arr.length; i++){
temp[arr[i]] = {};
temp = temp[arr[i]];
}
return nested;
}

strategies to reverse a linked list in JavaScript

I just struggled through a simple interview question: Please reverse a singly linked list.
While I failed to provide a working answer in time to save the interview, I was able to come up with a solution afterwards.
Is my solution correct? How would you analyze this with Big-Oh? Are there more efficient ways to reverse a singly linked list?
// reverse a linked list
var reverseLinkedList = function(linkedlist) {
var node = linkedlist;
var previous = null;
while(node) {
// reverse pointer
node.next = previous;
// increment previous to current node
previous = node;
// increment node to next node
if (node.next){
node = node.next
} else {
node = null;
}
}
}
Note: In my search for similar posts, I did find one example in JavaScript. I was wondering if my code is possible (without a temp variable). Thank you.
There are a couple of problems with your code. This should make it clear.
// reverse a linked list
var reverseLinkedList = function(linkedlist) {
var node = linkedlist;
var previous = null;
while(node) {
// save next or you lose it!!!
var save = node.next;
// reverse pointer
node.next = previous;
// increment previous to current node
previous = node;
// increment node to next node or null at end of list
node = save;
}
return previous; // Change the list head !!!
}
linkedlist = reverseLinkedList(linkedlist);
You could solve this problem recursively in O(n) time as ckersch mentions. The thing is, that you need to know that recursion is memory intensive since functions accumulate in the calls stack until they hit the stop condition and start returning actual things.
The way I'd solve this problem is:
const reverse = (head) => {
if (!head || !head.next) {
return head;
}
let temp = reverse(head.next);
head.next.next = head;
head.next = undefined;
return temp;
}
When reverse() reaches the end of the list, it will grab the last node as the new head and reference each node backwards.
This would be O(n) in time, since you do a constant number of operations on each node. Conceptually, there isn't a more efficient way of doing things (in terms of big-O notation, there's some code optimization that could be done.)
The reason why you can't exceed O(n) is because, in order to do so, you would need to skip some nodes. Since you need to modify each node, this wouldn't be possible.
Efficiency then comes down to a constant factor. The fewer operations you can do per item in the list, the faster your code will execute.
I'd implement like this:
function reverseLinkedList(list, previous){
//We need to use the the current setting of
//list.next before we change it. We could save it in a temp variable,
//or, we could call reverseLinkedList recursively
if(list.next !== null){
reverseLinkedList(list.next, list);
}
//Everything after 'list' is now reversed, so we don't need list.next anymore.
//We passed previous in as an argument, so we can go ahead and set next to that.
list.next = previous;
}
reverseLinkedList(list, null);
Of course, this is recursive, so it would be inefficient in terms of space, but I like recursive code :)
This also doesn't return the reversed linked list, but we could fairly easily modify things to do so if that were important.
ES6 solution:
Just keep a track of the reversed list and keep adding that to tmp.
const reverseLinkedList = (head) => {
let reversed = null;
while(head) {
const tmp = head;
head = head.next;
tmp.next = reversed;
reversed = tmp;
}
return reversed;
};
console.log(JSON.stringify(reverseLinkedList({
data: 1,
next: {
data: 2,
next: {
data: 3,
next: {
data: 4,
next: {
data: 5,
next: {
data: 5,
next: {
data: 6
}
}
}
}
}
}
})));
Reversing the SinglyLinkedList:
Input: 1->2->3->4->5->NULL
Output: 5->4->3->2->1->NULL
To understand The Solution we have to keep track of previous head and next variables
for example in above input Head = 1 ; next = 2 we don't have previous so assume previous = null
loop the list till head is not null. reverse the connections(previous and next) of head.
Below is the code
var reverseList = function(head) {
let previous = null;
while(head !== null){
let next = head.next;
head.next = previous;
previous= head
head = next;
}
return previous;
};
//O(n) | O(1) wherre n is the number of nodes in the linked list
class Node{
constructor(val){
this.val = val;
this.next = null;
}
}
function reverseLinkedList(head) {
if(!head) return null;
let p1 = head;
let p2 = null;
while(p1){
let temp = p1.next;
p1.next = p2;
p2 = p1;
p1 = temp;
}
return p2;
}
const a = new Node(1);
a.next = new Node(2);
a.next.next = new Node(3)
console.log("Current Node",a);
console.log("Reversed List",reverseLinkedList(a))
class LinkedList {
constructor () {
this.head = this.tail = null
}
// add to the end of the list
append (value) {
if (!this.tail) {
this.head = this.tail = new Node(value)
} else {
let oldTail = this.head
this.head = new Node(value)
this.head.next = oldhead
}
}
reverseList() {
//your code here
let currentNode = this.head
this.head = null
while(currentNode) {
if (!this.head) {
this.head = new Node(currenthead.data)
} else {
let oldhead = this.head
this.head = new Node(currentNode.data)
this.head.next = oldhead
}
currentNode = currentNode.next
}
}
}
class Node {
constructor (value, next) {
this.data = value
this.next = next || null
}
}
const list = new LinkedList()
list.append(1)
list.append(2)
list.reverseList()
Since inserting data at the beginning of the linked list pushes other first nodes till the end, and since it's a O(1) process.
Then I created the following function reverse()
where it basically insert node elements in the beginning which basically will get a reversed list at the end.
Here's a demo down below:
class Node {
constructor(data, next = null) {
this.data = data;
this.next = next;
}
}
class LinkedList {
constructor() {
this.head = null;
this.size = 0;
}
insertFirst(data = null) {
// make new head point to the previous head
this.head = new Node(data, this.head);
this.size ++;
}
insertLast(data = null) { // insert last in the beginning will be the first in the linked list
const node = new Node(data);
// If empty, insert first
if (!this.head) this.insertFirst(data);
else {
let current = this.head;
// while next is not null, continue
while (current.next)
current = current.next;
// eventually next is null, we want to set next here to the node we want to add
current.next = node;
}
this.size ++;
}
// print linked list
print() {
let current = this.head;
let output = "";
while (current) { // while current is not null, eventually it will be null
output += current.data + " => ";
current = current.next; // current jumping to the next node
}
output += "| NULL"; // ending
console.log(output);
return output;
}
reverse() {
if (!this.head) return; // if no head, do nothing
let current = this.head;
const linkedList = new LinkedList(); // create a new linked list
// don't worry, it will be garbage collected once this function ends since it's not a global variable
while (current) {
linkedList.insertFirst(current.data); // insert first at the beginning will be the end of the linked list at the end
current = current.next;
}
// assign current head to the reversed linked list head
this.head = linkedList.head;
}
}
const linkedList = new LinkedList();
// fill data as 100 -> 200 -> 300 -> 400
linkedList.insertLast(100);
linkedList.insertLast(200);
linkedList.insertLast(300);
linkedList.insertLast(400);
// To view results
const bodyElement = document.getElementsByTagName("body")[0];
bodyElement.innerHTML = `<p>Original Linked List: <b>${linkedList.print()}</b></p>`; // 100 200 300 400
linkedList.reverse();
bodyElement.innerHTML += `<p>Reversed Linked List: <b>${linkedList.print()}</b></p>`; // 400 300 200 100
b {
color: green;
}
<body></body>
Overall, the whole process of this reverse() function is O(n).
Hopefully this sounds clear to you, and correct me if I'm wrong.
This is my recursive solution:
https://codesandbox.io/s/reverse-linked-list-tqh2tq?file=/src/index.js
let d = { me: "d" };
let c = { me: "c", next: d };
let b = { me: "b", next: c };
let a = { me: "a", next: b };
const reverseMe = (o) => {
let lastDude;
if (o.next.next) lastDude = reverseMe(o.next);
else lastDude = o.next;
o.next.next = o;
o.next = null;
return lastDude;
};
console.log("result", reverseMe(a));

Categories