Javascript 遍历以多种方式相互连接的对象列表
我有一个充满对象的数组,其中每个对象都有指向数组中其他对象的“出口”。我想知道如何遍历这些项目并“跟踪”每个出口 基本思想是创建数组中对象的“映射” 基本上,每个对象都是这样(简化为仅显示重要部分): 从本质上讲,我希望一个算法遵循大于Javascript 遍历以多种方式相互连接的对象列表,javascript,arrays,graph,Javascript,Arrays,Graph,我有一个充满对象的数组,其中每个对象都有指向数组中其他对象的“出口”。我想知道如何遍历这些项目并“跟踪”每个出口 基本思想是创建数组中对象的“映射” 基本上,每个对象都是这样(简化为仅显示重要部分): 从本质上讲,我希望一个算法遵循大于-1的任何方向(n、s、e、w、u、d) 我自己也试着画出来,但我很困惑当一个物体有多个出口时会发生什么 这是我的小提琴: 基本上,我希望遍历数组并在画布上为每个区域输出一个正方形-因此,如果area1向东有一个“出口”,那么我希望在area1的右侧显示一个正方形
-1
的任何方向(n、s、e、w、u、d)
我自己也试着画出来,但我很困惑当一个物体有多个出口时会发生什么
这是我的小提琴:
基本上,我希望遍历数组并在画布上为每个区域输出一个正方形-因此,如果area1向东有一个“出口”,那么我希望在area1的右侧显示一个正方形,以此类推。您正在遍历一个图形。这里的要点是:
var visitRoom = function(rooms, roomId) {
if (roomId === -1)
return;
var room = rooms[roomId];
if (room.visited)
return;
room.visited = true;
doSomethingWithRoom(room);
visitRoom(rooms, room.n);
visitRoom(rooms, room.e);
visitRoom(rooms, room.s);
visitRoom(rooms, room.w);
visitRoom(rooms, room.u);
visitRoom(rooms, room.d);
};
visitRoom(rooms, 0); // assuming you're starting at the first room
这里的问题是:
- 存储
有点混乱,因为它使用遍历算法所需的中间状态污染原始数据room.visted
- 此代码假定每个房间的ID等于其在阵列中的索引。如果不是这样,您可能希望找到一种通过房间ID获取房间的方法。在这种情况下,房间ID和房间对象之间的映射比数组更有用
- 递归方法会在足够大的映射中耗尽堆栈内存。这可以通过使用迭代方法来解决,在迭代方法中,您不必通过递归访问房间,而是将其ID添加到要访问的房间列表中,然后继续访问列表中的第一个房间,直到该房间为空。与存储递归调用的堆栈帧相比,保留未访问房间的列表占用的内存更少
var visitAll = function(rooms) {
var toVisit = [0];
var visited = {};
while (toVisit.length > 0) {
var roomId = toVisit.pop();
var room = findRoomById(rooms, roomId);
doSomethingWithRoom(room);
visited[roomId] = true;
["n", "s", "e", "w", "u", "d"].forEach(function(exit) {
var exitId = room[exit];
if (exitId !== -1 && !visited[exitId])
toVisit.push(exitId);
});
}
}
var findRoomById = function(rooms, roomId) {
// do whatever you need to find the room with the correct ID
return rooms[roomId];
}
var doSomethingWithRoom = function(room) {
// do what you want here; this will be called once per visited room
}
visitAll(rooms);
如果还希望跟踪每个房间的空间坐标,也可以在第一次遇到每个房间时,根据前一个房间的坐标和所遵循的出口方向,为每个房间指定其位置 这实际上取决于您想要如何处理多个出口
var dirs = ["n", "e", "s", "w", "u", "d"];
var visited = {};
for(var i = 0; i < Areas.length; i++){
for (var j = 0; j < dirs.length; j++) {
if(Areas[i][dirs[j]] > -1){
doSomething(array[i].id, dirs[j], array[i][dirs[j]);
}
};
}
function doSomething(roomID, exitDirection, exitID){
//Called for every exit for every room.
if(visited[exitID]!== true){
visited[exitID] = true;
//Do whatever unique stuff you want to do here.
//This will get called for every new exit room but you may not want that if you're building doors or something.
}
}
var dirs=[“n”、“e”、“s”、“w”、“u”、“d”];
var={};
对于(变量i=0;i-1){
doSomething(数组[i].id,dirs[j],数组[i][dirs[j]);
}
};
}
函数doSomething(roomID、exitDirection、exitID){
//要求每个房间的每个出口。
如果(已访问[exitID]!==true){
已访问[exitID]=真;
//做任何你想在这里做的独特的事情。
//每一个新的出口房间都会被要求这样做,但如果你正在建造门或其他东西,你可能不想这样做。
}
}
这将为每个元素添加一个“其他”字段、一步一步包含所有可访问元素的结构化多维对象,以及一个包含可访问元素的简单列表的分配器数组
var Chernarus = [
{
id: 0,
name: "stary sobor",
description: "",
smell: "",
objects: [],
items: [],
clothes: [],
food: [],
barricades: [],
n:-1,s:3,e:1,w:-1,
u:-1,d:-1,
z:0,
bg:"img/centre.jpg"
},{
id: 1,
name: "novy sobor",
description: "",
smell: "",
objects: [],
items: [],
clothes: [],
food: [],
barricades: [],
n:-1,s:2,e:-1,w:0,
u:-1,d:-1,
z:0,
bg:"img/centre.jpg"
},{
id: 2,
name: "mogilevka",
description: "",
smell: "",
objects: [],
items: [],
clothes: [],
food: [],
barricades: [],
n:1,s:3,e:-1,w:-1,
u:-1,d:-1,
z:0,
bg:"img/centre.jpg"
},{
id: 3,
name: "dubky",
description: "",
smell: "",
objects: [],
items: [],
clothes: [],
food: [],
barricades: [],
n:2,s:4,e:-1,w:-1,
u:-1,d:-1,
z:0,
bg:"img/centre.jpg"
},{
id: 4,
name: "novo selky",
description: "",
smell: "",
objects: [],
items: [],
clothes: [],
food: [],
barricades: [],
n:3,s:5,e:-1,w:-1,
u:-1,d:-1,
z:0,
bg:"img/centre.jpg"
},{
id: 5,
name: "chernogorsk",
description: "",
smell: "",
objects: [],
items: [],
clothes: [],
food: [],
barricades: [],
n:4,s:-1,e:-1,w:6,
u:-1,d:-1,
z:0,
bg:"img/centre.jpg"
}
];
var toCheck=["n","s","e","w"];
var maxSteps=100;
function getOthers(element,recursion,alreadyDone,alreadyArr) {
if(recursion>maxSteps) return "TOO MANY:INFINITE?";
if(Chernarus[element]==undefined) return "NOT FOUND: "+element;
var item=Chernarus[element];
if(alreadyDone[element]!=undefined) return element+" ALREADY DONE";
alreadyDone[element]=true;
alreadyArr.push(element);
var out={};
for (var ch=0;ch<4;ch++) {
var tc=toCheck[ch];
var dir=item[toCheck[ch]];
if(dir>0) {
out[tc]={pos:dir,others:getOthers(dir,recursion+1,alreadyDone,alreadyArr)};
}
}
return out;
}
for (var i=0;i<Chernarus.length;i++) {
var allothers=[]
Chernarus[i]['others']=getOthers(i,1,[],allothers);
Chernarus[i]['allothers']=allothers;
}
alert(dump(Chernarus,""));
function dump(obj,spc) {
if(obj==undefined) return "<undefined>";
if((typeof obj)=="object") { // obj instanceof Array || obj.toString()=="[object Object]"
var out="";
for(var it in obj) if(obj.hasOwnProperty(it)) {
out+=spc+it+"= {\n";
out+= dump(obj[it],spc+" ");
out+=spc+"}\n";
}
return out;
} else return spc+(obj.toString())+"\n";
}
var Chernarus=[
{
id:0,
名称:“stary sobor”,
说明:“,
气味:“,
对象:[],
项目:[],
衣服:[],
食物:[],
路障:[],
n:1,s:3,e:1,w:1,
u:-1,d:-1,
z:0,
背景:“img/center.jpg”
},{
id:1,
姓名:“novy sobor”,
说明:“,
气味:“,
对象:[],
项目:[],
衣服:[],
食物:[],
路障:[],
n:1,s:2,e:1,w:0,
u:-1,d:-1,
z:0,
背景:“img/center.jpg”
},{
id:2,
名称:“莫吉列夫卡”,
说明:“,
气味:“,
对象:[],
项目:[],
衣服:[],
食物:[],
路障:[],
n:1,s:3,e:1,w:1,
u:-1,d:-1,
z:0,
背景:“img/center.jpg”
},{
id:3,
姓名:“dubky”,
说明:“,
气味:“,
对象:[],
项目:[],
衣服:[],
食物:[],
路障:[],
n:2,s:4,e:1,w:1,
u:-1,d:-1,
z:0,
背景:“img/center.jpg”
},{
id:4,
名称:“novo selky”,
说明:“,
气味:“,
对象:[],
项目:[],
衣服:[],
食物:[],
路障:[],
n:3,s:5,e:1,w:1,
u:-1,d:-1,
z:0,
背景:“img/center.jpg”
},{
id:5,
名称:“切尔诺戈尔斯克”,
说明:“,
气味:“,
对象:[],
项目:[],
衣服:[],
食物:[],
路障:[],
n:4,s:1,e:1,w:6,
u:-1,d:-1,
z:0,
背景:“img/center.jpg”
}
];
var-toCheck=[“n”、“s”、“e”、“w”];
var maxSteps=100;
函数getOthers(元素、递归、alreadyDone、alreadyArr){
如果(递归>最大步骤)返回“太多:无限?”;
如果(Chernarus[element]==未定义)返回“未找到”:+element;
var项目=Chernarus[元素];
if(alreadyDone[element]!=undefined)返回元素+“已完成”;
alreadyDone[element]=true;
推力(元件);
var out={};
对于(变量ch=0;ch0){
out[tc]={pos:dir,others:getOthers(dir,递归+1,alreadyDone,alreadyArr)};
}
}
返回;
}
对于(var i=0;i您是否在遍历所有对象后试图找到最终位置?@closure-基本上我希望遍历数组并在画布上为每个区域输出一个正方形-因此,如果area1有一个“出口”向东,那么我希望在数组右侧显示一个正方形
var Chernarus = [
{
id: 0,
name: "stary sobor",
description: "",
smell: "",
objects: [],
items: [],
clothes: [],
food: [],
barricades: [],
n:-1,s:3,e:1,w:-1,
u:-1,d:-1,
z:0,
bg:"img/centre.jpg"
},{
id: 1,
name: "novy sobor",
description: "",
smell: "",
objects: [],
items: [],
clothes: [],
food: [],
barricades: [],
n:-1,s:2,e:-1,w:0,
u:-1,d:-1,
z:0,
bg:"img/centre.jpg"
},{
id: 2,
name: "mogilevka",
description: "",
smell: "",
objects: [],
items: [],
clothes: [],
food: [],
barricades: [],
n:1,s:3,e:-1,w:-1,
u:-1,d:-1,
z:0,
bg:"img/centre.jpg"
},{
id: 3,
name: "dubky",
description: "",
smell: "",
objects: [],
items: [],
clothes: [],
food: [],
barricades: [],
n:2,s:4,e:-1,w:-1,
u:-1,d:-1,
z:0,
bg:"img/centre.jpg"
},{
id: 4,
name: "novo selky",
description: "",
smell: "",
objects: [],
items: [],
clothes: [],
food: [],
barricades: [],
n:3,s:5,e:-1,w:-1,
u:-1,d:-1,
z:0,
bg:"img/centre.jpg"
},{
id: 5,
name: "chernogorsk",
description: "",
smell: "",
objects: [],
items: [],
clothes: [],
food: [],
barricades: [],
n:4,s:-1,e:-1,w:6,
u:-1,d:-1,
z:0,
bg:"img/centre.jpg"
}
];
var toCheck=["n","s","e","w"];
var maxSteps=100;
function getOthers(element,recursion,alreadyDone,alreadyArr) {
if(recursion>maxSteps) return "TOO MANY:INFINITE?";
if(Chernarus[element]==undefined) return "NOT FOUND: "+element;
var item=Chernarus[element];
if(alreadyDone[element]!=undefined) return element+" ALREADY DONE";
alreadyDone[element]=true;
alreadyArr.push(element);
var out={};
for (var ch=0;ch<4;ch++) {
var tc=toCheck[ch];
var dir=item[toCheck[ch]];
if(dir>0) {
out[tc]={pos:dir,others:getOthers(dir,recursion+1,alreadyDone,alreadyArr)};
}
}
return out;
}
for (var i=0;i<Chernarus.length;i++) {
var allothers=[]
Chernarus[i]['others']=getOthers(i,1,[],allothers);
Chernarus[i]['allothers']=allothers;
}
alert(dump(Chernarus,""));
function dump(obj,spc) {
if(obj==undefined) return "<undefined>";
if((typeof obj)=="object") { // obj instanceof Array || obj.toString()=="[object Object]"
var out="";
for(var it in obj) if(obj.hasOwnProperty(it)) {
out+=spc+it+"= {\n";
out+= dump(obj[it],spc+" ");
out+=spc+"}\n";
}
return out;
} else return spc+(obj.toString())+"\n";
}