Thank you in advance for any help.
Why does the return statement from return this.visited inside the if(this.queue.length === 0) code block return undefined? Whereas both console.logs before the return statement return the correct values.
What I tried: I read through a few related post here and then tried binding this to the this.traverse method. I reviewed the syntax, logic, checked for typos several times.
const Tree = require('../Tree/treeExport')
const Queue = require('../Stack_Queue/queueExport')
class BFS extends Tree {
constructor(queue,queue1) {
super()
this.visited = queue
this.queue = queue1
this.traverse = this.traverse.bind(this)
}
traverse() {
let current;
if(this.visited.length < 1) {
this.queue.enqueue(this.root)
}
if(this.queue.length > 0) {
current = this.queue.dequeue()
}
if(current.left) {
this.queue.enqueue(current.left)
}
if(current.right) {
this.queue.enqueue(current.right)
}
if(current) {
this.visited.enqueue(current.value)
}
if(this.queue.length === 0) {
console.log(this.visited, '\n \n')
console.log(this.mapToArray(this.visited), '\n \n')
return this.visited;
} else {
this.traverse()
}
}
mapToArray(queue) {
const array = []
let temp;
while(queue.length > 0) {
temp = queue.dequeue()
array.push(temp)
}
temp = null;
return array;
}
}
let queue = new Queue
let visited = new Queue
const bfs = new BFS(visited,queue)
bfs.insert(5)
bfs.insert(3)
bfs.insert(7)
bfs.insert(2)
bfs.insert(4)
bfs.insert(6)
bfs.insert(9)
console.log(bfs.traverse())
result from console:
Queue {
first: Node { value: 5, next: Node { value: 3, next: [Node] } },
last: Node { value: 9, next: null },
length: 7
}
[
5, 3, 7, 2,
4, 6, 9
]
undefined
Related
Cant understand why do i need to write return inside each if and else, but not once after conditional statement`s block?
Proper return use
let arrayToList = arr => {
if(arr.length == 1)
{
let list = {
value: arr.shift(),
rest: null
};
return list;
}
else{
let list = {
value: arr.shift(),
rest: arrayToList(arr)
};
return list;
}
};
console.log(arrayToList([10, 20]));
//{value: 10, rest: {value: 20, rest: null}}
Misuse
let arrayToList = arr => {
if(arr.length == 1)
{
let list = {
value: arr.shift(),
rest: null
};
}
else{
let list = {
value: arr.shift(),
rest: arrayToList(arr)
};
}
return list;
};
console.log(arrayToList([10, 20]));
//{
//value: 1
//rest: {
//value: 2
//rest: {value: 3, rest: null}
//}
//}
The problem involves scope
Your problem is that you've defined list inside the if/else scope and not outside. This code would work in Python, but Javascript works differently. The solution is to define list in an exterior scope:
let arrayToList = arr => {
let list = {}
if(arr.length == 1)
{
list = {
value: arr.shift(),
rest: null
};
}
else{
list = {
value: arr.shift(),
rest: arrayToList(arr)
};
}
return list;
};
I happen to think it is more readable to do the following:
let arrayToList = arr => {
if(arr.length == 1)
{
return {
value: arr.shift(),
rest: null
};
}
return {
value: arr.shift(),
rest: arrayToList(arr)
};
};
But this is a mostly aesthetic consideration
Recursion is a functional heritage and so using it with functional style yields the best results -
// List.js
const empty =
null
const create = (value, rest = empty) =>
({ value, rest })
const fromArray = (a = []) => // <-- "arrayToList"
a.length === 0
? empty
: create(a[0], fromArray(a.slice(1)))
export { fromArray }
// Main.js
import { fromArray } from "./List"
const mylist =
fromArray([1, 2, 3])
console.log(mylist)
// { value: 1, rest: { value: 2, rest: { value: 3, rest: null } } }
Expand the snippet below to verify the results in your browser -
const empty =
null
const create = (value, rest = empty) =>
({ value, rest })
const fromArray = (a = []) =>
a.length === 0
? empty
: create(a[0], fromArray(a.slice(1)))
const mylist =
fromArray([1,2,3])
console.log(mylist)
// { value: 1, rest: { value: 2, rest: { value: 3, rest: null } } }
let creates blocked scoped variables. Change the declaration to use var.
let arrayToList = arr => {
if(arr.length == 1) {
var list = {
value: arr.shift(),
rest: null
};
} else {
var list = {
value: arr.shift(),
rest: arrayToList(arr)
};
}
return list;
};
console.log(arrayToList([10, 20]));
Or, since you'll want list to start out as an object in either case, you can just set it up prior to the if and populate it based on the condition.
let arrayToList = arr => {
// You know you want list to be an object
// either way, so declare it ahead of time
// and populate it later.
let list = {};
if(arr.length == 1) {
list = {
value: arr.shift(),
rest: null
};
} else {
list = {
value: arr.shift(),
rest: arrayToList(arr)
};
}
return list;
};
console.log(arrayToList([10, 20]));
I have a recursive function (exploreNode)that updates the value of a variable (branch_queue) that is declared right above it.
When I run normally (without a closure function), it works as expected.
When I place inside of a closure function, the recursive function doesn't iterated through children nodes the way its supposed to. it remains on the same initial node, until a "Max Call Stack" error fires.
The purpose of the recursive function is to explore a JSON tree, until a desired ID is found. As it traverses through the tree, the branch_queue var is updated with the roadmap to the node of interest.
The closure was to not have the branch_queue as a global function.
I tried both in es6 and es5, thinking it could be a problem with scope and using "const" and "let".
The examples are below.
I also have the code block below that worked without the closure.
Tree that I feed in as a parameter
let u = [
{
id: 0,
label: 'l0',
children: [
{
id: 1,
label: 'l1'
},
{
id: 2,
label: 'l2',
children: [
{
id: 3,
label: 'l3'
},
{
id: 4,
label: 'l4'
},
{
id: 5,
label: 'l5'
},
{
id: 6,
label: 'l6',
children: [
{
id: 7,
label: 'l7'
},
{
id: 8,
label: 'l8'
},
{
id: 9,
label: 'l9'
},
{
id: 10,
label: 'l10'
}
]
}
]
}
]
}
]
WHAT DID WORK
let branch_queue = [];
// Assumes that the ID exists!
const exploreNode = (nodeIdOfInterest, nodeTree) => {
// var branch_queue = [];
for (let i = 0; i < nodeTree.length; i++) {
const nodeToCheck = nodeTree[i];
if (nodeToCheck.id == nodeIdOfInterest) {
branch_queue.push(nodeToCheck.id);
return nodeToCheck.label;
} else if(nodeToCheck.children) {
branch_queue.push(nodeToCheck.id);
return exploreNode(nodeIdOfInterest, nodeToCheck.children);
}
}
}
exploreNode(3, contentTree);
console.log(branch_queue); // prints the correct roadmap
WHAT DOESN'T WORK
ES5
function fn (nodeIdOfInterest, nodeTree) {
let branch_queue = [];
console.log('here');
// Assumes that the ID exists!
function exploreNode () {
var branch_queue = [];
console.log('in here');
for (var i = 0; i < nodeTree.length; i++) {
var nodeToCheck = nodeTree[i];
console.log(`${nodeToCheck.label} : ${nodeToCheck.id}`);
if (nodeToCheck.id == nodeIdOfInterest) {
console.log('found it');
branch_queue.push(nodeToCheck.id);
return nodeToCheck.label;
} else if(nodeToCheck.children) {
console.log('checking children');
branch_queue.push(nodeToCheck.id);
return exploreNode(nodeIdOfInterest, nodeToCheck.children);
}
}
};
exploreNode();
return branch_queue;
}
console.log(fn(3, contentTree)); // throws call stack error
ES6
const fn = (nodeIdOfInterest, nodeTree) => {
let branch_queue = [];
console.log('here');
// Assumes that the ID exists!
const exploreNode = () => {
// var branch_queue = [];
console.log('in here');
for (let i = 0; i < nodeTree.length; i++) {
let nodeToCheck = nodeTree[i];
console.log(`${nodeToCheck.label} : ${nodeToCheck.id}`);
if (nodeToCheck.id == nodeIdOfInterest) {
branch_queue.push(nodeToCheck.id);
return nodeToCheck.label;
} else if(nodeToCheck.children) {
branch_queue.push(nodeToCheck.id);
return exploreNode(nodeIdOfInterest, nodeToCheck.children);
}
}
};
exploreNode();
return branch_queue;
};
console.log(fn(3, contentTree)); // throws call stack error
Expected output => [0 2 3]
Actual => . Max call stack error
The recursive function never moves beyond the very first level, and repeats indefinitely.
nodeTree in your recursive version of exploreNode is always the same starting point, the one passed into fn. Every call to exploreNode in that version starts fresh: Your calls to exploreNode are passing arguments, but it's ignoring them. The "what did work" version isn't ignoring the arguments passed to it, so it works.
var swapPairs = function(head) {
if (head == null || head.next == null) {
return;
}
let oldHead = head;
let nextHead = head.next;
oldHead.next = swapPairs(nextHead.next);
head.next = oldHead;
return head;
};
console.log(swapPairs(list.head));
Any clue why Node JS responds with each head but responds with a next value of "[circular]"?
For example:
{ value: 16, next: [Circular] }
Because it's circular - it's infinitely nested:
value: 16,
next: {
next: {
next: {...}
}
}
export class EstimateForm extends React.Component<IEstimateFormProps,
IEstimateFormState> {
state: IEstimateFormState = {
cellUpdateCss: 'red',
toRow: null,
fromRow: null,
estimateList: null,
estimateItemList: [],
poseList: null,
levelList: null,
partList: null,
selectedEstimate: null,
totalEstimateItems: 0,
selectedIndexes: [],
totalEstimateAmount: 0,
grid: null,
projectId: 0,
};
constructor(props, context) {
super(props, context);
this.state.estimateList = this.props.estimateList;
}
rowGetter = i => {
const row = this.state.estimateItemList[i];
const selectRevison = this.state.selectedEstimate.revision;
if (row['pose.poseName']) {
const poseCode =
row['pose.poseName'].substring(row['pose.poseName'].lastIndexOf('[') + 1,
row['pose.poseName'].lastIndexOf(']'));
for (const pose of this.state.poseList) {
if (pose.poseCode === poseCode) {
row.pose = pose;
}
}
}
if (row['level.levelName']) {
const levelCode = row['level.levelName'].substring(
row['level.levelName'].lastIndexOf('[') + 1,
row['level.levelName'].lastIndexOf(']')
);
for (const level of this.state.levelList) {
if (level.levelCode === levelCode) {
row.level = level;
}
}
}
if (row['level.part.partName']) {
const partCode = row['level.part.partName'].substring(
row['level.part.partName'].lastIndexOf('[') + 1,
row['level.part.partName'].lastIndexOf(']')
);
for (const part of this.state.partList) {
if (part.partCode === partCode) {
row.part = part;
}
}
}
row.get = key => eval('row.' + key);
row.totalCost = (row.materialCost + row.laborCost) * row.amount;
const changeColor = {
backgroundcolor: 'red'
};
const all = document.getElementsByClassName('react-grid-Row') as
HTMLCollectionOf<HTMLElement>;
debugger; if (row.revision > selectRevison) {
for (let i = this.state.fromRow; i <= this.state.toRow; i++) {
all[i].style.color = 'red'; //HERE
}
return row;
}
}
handleGridRowsUpdated = ({ fromRow, toRow, updated }) => {
const rows = this.state.estimateItemList.slice();
for (let i = fromRow; i <= toRow; i++) {
const rowToUpdate = rows[i];
const updatedRow = update(rowToUpdate, { $merge: updated });
rows[i] = updatedRow;
}
this.setState({ estimateItemList: rows, fromRow: (fromRow), toRow: (toRow)
}, () => {
});
};
saveEstimateItems = () => {
if (this.state.selectedEstimate == null) {
toast.warn(<Translate
contentKey="bpmApp.estimateForm.pleaseSelectEstimate">Please select an
estimate</Translate>);
return;
}
render() {
return ()
}
I wanna to change the row color when the condition row.revision > this.state.selectedEstimate.revision . How can I prevent the change of this.color. However TypeError: Cannot read property 'style' of undefined get error but row color is not change. how can i solve this problem it is my first project in react and i dont know where is the problemThanks for your feedback guys.
Okay, so without the rest of the context because your pasted code is difficult to read and understand, the simplest reason for your issue is in this chunk:
const all = document.getElementsByClassName('react-grid-Row') as
HTMLCollectionOf<HTMLElement>;
debugger; if (row.revision > selectRevison) {
for (let i = this.state.fromRow; i <= this.state.toRow; i++) {
all[i].style.color = 'red'; //HERE
}
Essentially there's multiple things that could go wrong here, but most likely there are either no rows with that class on the page, or less than your this.state.fromRow, I see you've got the debugger in there, but you are missing a few things:
You aren't doing a null check on all to make sure you are finding something
You aren't checking whether all.length > this.state.fromRow
You aren't breaking the for loop if all.length < this.state.toRow
It's failing because all[i] doesn't exist, or there's no values:
all = [0, 1]
and you are looking for all[3] for example
Throw in those fallbacks and check what all is on page load and you should be able to figure it out.
I applied for a job where I was given this task. I had to write a function reversePrint() which returns a reversed array with values from a passed object.
Here is the object
var someList = {
value: 1,
next: {
value: 2,
next: {
value: 3,
next: {
value: 4,
next: null
}
}
}
};
My attempt
function reversePrint(linkedList) {
// empty array with the result
var b = [];
// while loop to check if current next is not null
while ( linkedList.next !== null ) {
// push current value into the array
b.push(linkedList.value);
// go one level deeper
linkedList = linkedList.next;
}
// push the last value into the array
b.push(linkedList.value);
// return reversed array
return b.reverse();
}
The function works, but I have a feeling that there is a better way to do this. I have already searched stackoverflow for javascript recursive operations, but could not find anything that would be considered a duplicate. Is there a more efficient way to do this?
There's nothing fundamentally wrong with your code, but your instinct is right: a recursive solution would seem to match the recursive nature of the data structure better, would be more concise, and also can be written to avoid the reverse.
var someList = {value: 1, next: {
value: 2, next: {
value: 3, next: {
value: 4, next: null}}}};
function reversePrint(input) {
return !input ? [] : reversePrint(input.next).concat(input.value);
}
console.log(reversePrint(someList));
Note that this solution is not tail-optimizable and might be best avoided if the input could be very deep. A tail-optimizable solution would be:
function reversePrint(input) {
return function inner(input) {
return !input ? [] : [input.value].concat(inner(input.next));
}(input).reverse();
}
Avoiding reverse with the iterative solution is possible, of course, but it requires an expensive unshift onto the front of the array at each step. On the other hand, the recursive solutions create multiple arrays of gradually increasing length, which is not exactly cheap either.
Using recursion you can also do it like this.
var someList = {
value: 1,
next: {
value: 2,
next: {
value: 3,
next: {
value: 4,
next: null
}
}
}
};
function reversePrint(linkedList) {
var r = []
if(linkedList.next) r = r.concat(reversePrint(linkedList.next))
r.push(linkedList.value)
return r
}
console.log(reversePrint(someList))
https://jsfiddle.net/zwzecvqf/2/
Here you have a recursive function.
function reversePrint (item) {
var nextItem = item.next
var items
if (nextItem) {
items = reversePrint(nextItem)
} else {
items = [];
}
items.push(item.value)
return items
}
Yet another recursive solution, but avoiding creating and throwing away multiple intermediary arrays:
function reversePrint(node, array) {
// Fill in the array if not given
array = array || [];
// Recurse if appropriate
if (node.next) {
reversePrint(node.next, array);
}
// Add the value on the way out
array.push(node.value);
return array;
}
function reversePrint(node, array) {
array = array || [];
if (node.next) {
reversePrint(node.next, array);
}
array.push(node.value);
return array;
}
var someList = {
value: 1,
next: {
value: 2,
next: {
value: 3,
next: {
value: 4,
next: null
}
}
}
};
console.log(reversePrint(someList));
What about not using recursion? I didn't find information this is not banned.
var someList = {
value: 1,
next: {
value: 2,
next: {
value: 3,
next: {
value: 4,
next: null
}
}
}
};
function reversePrint()
{
var currentNode = someList;
var cacheList = [];
do
{
cacheList.push(currentNode.value);
currentNode = currentNode.next;
}
while(currentNode != null);
cacheList.reverse();
return cacheList;
}
var reverseList = reversePrint(); // [4,3,2,1]
Here using a recursive function to sub objects values
function reversePrint(linkedList) {
// empty array with the result
var b = [];
function addValues(subList){
if(linkedList.next)
addValues(linkedList.next);
b.push(item.value);
}
addValues(linkedList);
return b.revers();
}