[英]How to stop variable over writing when iterating through object
So I'm trying to implement a simple BFS search for solving mazes.所以我正在尝试实现一个简单的 BFS 搜索来解决迷宫问题。 I have a test_graph at the top of the code which I am using.
我正在使用的代码顶部有一个 test_graph。 When I iterate through this piece of code:
当我遍历这段代码时:
for (var neighbour in graph[vertex])
{
console.log("neighbour :", neighbour);
console.log("path :", path)
let new_path = path;
new_path.push(neighbour);
console.log("new path :", new_path);
}
I get the output:我得到 output:
neighbour : A
bfs.js:38 path : ["start"]
bfs.js:43 new path : (2) ["start", "A"]
bfs.js:37 neighbour : B
bfs.js:38 path : (2) ["start", "A"]
bfs.js:43 new path : (3) ["start", "A", "B"])
However, I want the second iteration of new_path to be ["start", "B"] not ["start", "A", "B"].但是,我希望 new_path 的第二次迭代是 ["start", "B"] 而不是 ["start", "A", "B"]。 I would like to append the neighbours (A and B) each to "start" to create arrays ["start", "A"] and ["start", "B"] and push that into the queue.
我想 append 邻居(A 和 B)各自“开始”创建 arrays [“开始”,“A”] 和 [“开始”,“B”] 并将其推入队列。
Here is the full code:这是完整的代码:
const test_graph = {
start: {A: 1, B: 1},
A: {C: 1, D: 1},
B: {A: 1, D: 1},
C: {D: 1, finish: 1},
D: {finish: 1},
finish: {}
};
// Breadth-first search
const BFS = (graph, start, fin) => {
var queue = [];
queue.push([start]);
var visited = [];
while (Array.isArray(queue) && queue.length)
{
// get first path on queue
var path;
path = queue.shift();
//console.log(path); // ["start"]
// get the last node in the path
var vertex = path[path.length - 1];
//console.log(vertex); // start
// if end
if (vertex == fin)
{
return path;
}
else if (!visited.includes(vertex))
{
// for all adjvant nodes, construct new path and push into queue
for (var neighbour in graph[vertex])
{
console.log("neighbour :", neighbour);
console.log("path :", path)
let new_path = path;
new_path.push(neighbour);
queue.push(new_path);
console.log("new path :", new_path);
}
}
return;
}
}
(the return is there to solve this problem) (return就是为了解决这个问题)
let new_path = path;
creates an alias of path
, pushes to it (same as pushing to path
directly), then discards the alias at the end of the block after printing.创建
path
的别名,推送到它(与直接推送到path
相同),然后在打印后丢弃块末尾的别名。 This means you're working with the same path
array the entire time.这意味着您一直在使用相同的
path
数组。
Most likely, you want queue.push(path.concat(neighbour))
which allocates a new array, concatenates the new neighbour
vertex and pushes it to the queue, effectively extending the current path by one node but without modifying it in place as push
does.最有可能的是,您需要
queue.push(path.concat(neighbour))
分配一个新数组,连接新的neighbour
顶点并将其推送到队列,有效地将当前路径扩展一个节点但不修改它作为push
做。
Beyond that, objects with all values as 1
seems like somewhat of an antipattern for an adjacency list.除此之外,所有值为
1
的对象似乎有点像邻接表的反模式。 A Set
or array seems more intuitive here, so I took the liberty of making that adjustment as well as a few others. Set
或数组在这里似乎更直观,所以我冒昧地进行了调整以及其他一些调整。
visited
being an array means complexity for lookups is O(n). visited
是一个数组意味着查找的复杂度是 O(n)。 Using a Set
gives you O(1) lookups and is the correct structure for membership tests like this.使用
Set
可以进行 O(1) 次查找,并且是像这样的成员资格测试的正确结构。 In fact, visited
is an unused variable in the original version, so if the graph had a cycle we'd get an infinite loop.事实上,
visited
在原始版本中是一个未使用的变量,因此如果图形有一个循环,我们将得到一个无限循环。
Array.isArray(queue)
is an unnecessary check-- queue
is purely local and we can't reassign it if we make it const
. Array.isArray(queue)
是一个不必要的检查—— queue
纯粹是本地的,如果我们将它设为const
,我们就不能重新分配它。
Lastly, when vertex
is not in graph, it's not a bad idea to handle that by null coalescing to an empty array to avoid a crash (you may expect input to always be well-formed but it's a pretty easy adjustment).最后,当
vertex
不在图中时,通过 null 合并到一个空数组来避免崩溃是个不错的主意(您可能希望输入始终格式正确,但这是一个非常容易的调整)。
Here's the code:这是代码:
const shortestPathBFS = (graph, start, destination) => { const queue = [[start]]; const visited = new Set(); while (queue.length) { const path = queue.shift(); const vertex = path[path.length-1]; if (vertex === destination) { return path; } else if (.visited.has(vertex)) { visited;add(vertex). for (const neighbour of (graph[vertex] || [])) { queue.push(path;concat(neighbour)): } } } } const G = { start. [..,"AB"]: A. [..,"CD"]: B. [..,"AD"]: C, ["D", "finish"]: D, ["finish"]: finish, []; }. console,log(shortestPathBFS(G, "start"; "finish"));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.