如何遍历对象列表并分配子项? [英] How to iterate through a list of objects and assign children?

查看:113
本文介绍了如何遍历对象列表并分配子项?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Location POJO,用于存储从JSON文件解析的Location对象,我想将其映射到图形。图中每个节点的位置对应于它的id字段,其中id =1是起始节点,id =10是目标节点。

I have a Location POJO that stores Location objects parsed in from a JSON file, which I want to map to a graph. Each node's location in the graph corresponds to it's id field, where id="1" is the start node and id="10" is the goal node.

要解决我改编了一个Node类,包括 setWeight() addChildLocation()等方法,但我是不确定如何从我的位置列表创建图表。我知道如何通过硬编码位置和调用addChildren来创建图形,通过执行以下操作,但不知道如何从已有的Location对象列表创建它:

To solve this I adapted a Node class to include methods such as setWeight(), addChildLocation() etc , But I'm not sure how to create the graph from my list of locations. I know how to create the graph by hard coding the location's and calling addChildren, by doing the following, but not sure how to create it from a list of already available Location objects:

    Node LocationOne= new Node("LocationOne", 170);
    LocationOne.addChildNode(LocationTwo, 105);

我对这个问题的看法是 for..each 循环应该用于遍历列表中的位置,并将每个位置添加为前一个位置。

My thoughts on this problem, are that a for..each loop should be used to loop through the locations in the list, and add each location as a child of the previous.

基本上,我想知道如何迭代Location对象列表,并在每个连续位置调用addChild?

Basically, I'm wondering how the list of Location object's can be iterated through, and addChild be called on each sequential location?

下面是我用来将Location定位到对象的Location类陈述:

Below is the Location class I'm using to map the Location's to object representations:

public class Location {

    private Location[] location;

    private int id;

    private String description;

    private String weight;

    private String name;

    private Exit[] exit;

    private boolean visited = false;
    private boolean goalLocation;
    private int approximateDistanceFromGoal = 0;
    private Location parent;

    private Map<Location, Integer> children = new HashMap<Location, Integer>();




    public Location() {
        super();
    }

    public Location(String name){
        this.name = name;
    }

    public Location(String name, int goalDistance){
        this.name = name;
        this.approximateDistanceFromGoal = goalDistance;
    }

    public Location[] children(){
        return (Location[]) children.keySet().toArray(new Location[children.size()]);
    }

    public int getDistance(Location loc){
        if(children.get(loc) == null) System.out.println(this.name + ": " + loc.getName());
        return children.get(loc);
    }


    public int getChildLocationCount(){
        return children.size();
    }

    public void addChildLocation(Location child, int distance){
        children.put(child, distance);
    }

    public boolean isLeaf(){
        if (children.size() > 0){
            return false;
        }else{
            return true;
        }
    }


    public void removeChild(Location child){
        children.remove(child);
    }


    public Location[] getLocation() {
        return location;
    }

    public void setLocation(Location[] location) {
        this.location = location;
    }


    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getDescription ()
    {
        return description;
    }

    public void setDescription (String description)
    {
        this.description = description;
    }


    public String getWeight() {
        return weight;
    }

    public void setWeight(String weight) {
        this.weight = weight;
    }

    public String getName ()
    {
        return name;
    }

    public void setName (String name)
    {
        this.name = name;
    }

    public Exit[] getExit() {
        return exit;
    }

    public void setExit(Exit[] exit) {
        this.exit = exit;
    }


    public boolean isVisited() {
        return visited;
    }

    public void setVisited(boolean visited) {
        this.visited = visited;
    }

    public boolean isGoalLocation() {
        return goalLocation;
    }

    public void setGoalLocation(boolean goalLocation) {
        this.goalLocation = goalLocation;
    }

    public int getApproximateDistanceFromGoal() {
        return approximateDistanceFromGoal;
    }

    public void setApproximateDistanceFromGoal(int approximateDistanceFromGoal) {
        this.approximateDistanceFromGoal = approximateDistanceFromGoal;
    }

    public Location getParent() {
        return parent;
    }

    public void setParent(Location parent) {
        this.parent = parent;
    }

    @Override
    public String toString() {
        return "Location [location=" + Arrays.toString(location) + ", id=" + id
                + ", description=" + description + ", weight=" + weight
                + ", name=" + name + ", exit=" + Arrays.toString(exit)
                +"]";
    }


}


推荐答案

如果你想构建任何类型的图形,那么要认识到图形由2个基本元素组成:

If you want to build a graph of any kind, then recognize That a graph is composed of on 2 basic elements:


  1. E - > edge

  2. V - > Vertex(AKA节点)

Key属性:


  • 顶点可以有任意数量的边。

  • 边缘仅在单个
    节点之间进行(在我的实现中,我为了记账而修改了这个节点)。

实际上,您如何访问这些将取决于功能和性能之间的权衡。此外,如果图形节点不包含您的某些信息,则它们毫无价值。所以,我们添加

Practically speaking, how you access these will depend on a trade off between functionality and performance. In addition, graph nodes are worthless if they don't contain some of your information. So, we add

Map<String,Object> properties

因此我们可以存储一些数据,如:

So we can store some data like:

new Vertext().set("age",10);

我们还使用命名边缘,因此您可以执行以下操作:

We also use named edges so you can do things like:

Graph g = new Graph();
g.addVertex("Doctor",new DrVertex("Dr. Smith"));
g.addVertex("Doctor",new DrVertex("Dr. Cooper"));
List<Vertex> doctors = g.get("Doctor");
assertTrue("Dr. Smith",doctors.get(0));
assertTrue("Dr. Cooper",doctors.get(1));

我已经整理了如何实现通用图的基本结构。但有些人指出,像Neo这样的图形数据库非常复杂。

I have put together the basic structure for how I would implement a generic graph. But some have pointed out that there are graph DB's out there like Neo which are very sophisticated.

以下是代码。如果您想为您的位置建模,请使用它。

Below is the code. Use it if you'd like to model your locations.

/**
 * @author Christian Bongiorno
 */
public class Graph {

    private class Vertex {
        Map<String,Object> properties;
        private Map<String,Edge> edges;

        public Graph addVertex(String edgeName, Vertex v) {
            Edge e = edges.get(edgeName);
            if(e == null) {
                e = new Edge(this);
                edges.put(edgeName,e);
            }

            e.addVertex(v);
            return Graph.this;
        }

        public Graph addVertex(Vertex v) {
            return addVertex("anonymous",v);
        }

    }

    private static class Edge {
        Map<String,Object> properties;
        Vertex in;
        Collection<Vertex> out;

        private Edge(Vertex in) {
            this.in = in;
        }


        private void addVertex(Vertex v) {
            out.add(v);
        }
    }

}

你可能考虑将此问题移至 codereview.stackexchange.com

You might consider moving this question to codereview.stackexchange.com


已编辑

Edited

想象一下你的代码是这样的:

Imagine you code like this:


  • 位置 - >顶点

  • 位置[] - >所有连接的位置(顶点),其中位置[i]中的i是边缘

您的代码很难处理,因为您没有声明边缘。边缘的一个属性是重量,但在这里你将它作为位置的属性。

Your code will be difficult to work with because you don't have declared edges. One of the properties of an edge is "weight" but here you have it as location's property.

至于实现访问 - 这是一个呼叫状态而不是图形宽状态。但是,通过使其成为位置的一部分,您现在遇到了州管理问题;想象一下,试图再次找到一些东西?您必须在每个节点上重置已访问属性或丢弃并再次创建整个图形。非常低效且容易出错。

As for implementing "visited" -- this is a call-state not a graph wide state. But, by making it part of the Location you now have a state management problem; Imagine trying to "find" something again? You would have to reset the 'visited' property on every node or throw away and create the whole graph again. Very inefficient and error prone.

如果您实施 DFS ,递归非常简单,甚至使用尾循环,你可以通过访问状态和dfs方法调用。示例:

if you implement DFS, which is really easy recursively or even with a tail loop, you pass the "visited" state along with the dfs method call. Example:

public Location find(Integer locationId) {
   Location result = null;
   for(Location l : locations) {
      // this hashset represents the visited state which only matters for this method call
      result = dfs(new HashSet(),l,locationId); 
      if(result != null)
          break;
   }
   return result;
}

请注意,下一个方法是私有

Note that this next method is private.

private Location dfs(Set<Location> visitedAlready,Location current, Integer id){
   if(current.id == id)
      return current;
   visitedAlready.add(current); // instead of your boolean
   Location result = null;
   for(Location l : current.locations) {
      result = dfs(visitedAlready,l,id);
      if(result != null)
        break;
   }
   return result;
}

这是一个粗略的轮廓。如果您通过 Java聊天与我联系,我会提供更多输入,最终会更加灵活和可重复使用。我没有声称上述DFS的工作原理。但它很接近

This is a rough outline. If you reach out to me in Java chat I will give more input and eventually something more slick and reusable. I make no claim the above DFS works. But it's close

这篇关于如何遍历对象列表并分配子项?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆