简体   繁体   English

更改多维树的“视角”

[英]Change “perspective” of multi-dimension tree

|-- Car                                |-- Green     
|   |-- Audi                           |   |-- Car        
|   |   |-- Green                      |   |   `-- Audi           
|   |   |-- Blue                       |   `-- Bike             
|   |   `-- Red                        |       `-- BMW  
|   `-- BMW                            |-- Blue     
|       |-- Red                        |   `-- Car         
|       `-- Yellow     ==========>     |       `-- Audi     ==========>     etc.                 
`-- Bike                               |-- Red         
    |-- BMW                            |   |-- Car    
    |   |-- Yellow                     |   |   |-- Audi 
    |   |-- Blue                       |   |   `-- BMW
    |   `-- Green                      |   `-- Bike       
    `-- Honda                          |       `-- Honda       
        |-- Red                        `-- Yellow          
        `-- Yellow                         |-- Car         
                                           |   `-- BMW
                                           `-- Bike
                                               |-- BMW
                                               `-- Honda

I want to implement several "perspectives" in a tree builder, in a generic fashion . 我想以通用的方式在树构建器中实现几个“视角”。

There are 6 possible permutations of this tree, I've just drawn 2 of them. 该树有6个可能的排列,我刚刚画了其中的2个。

What I tried: 我试过的

  • I'm using a generic tree structure, where every node knows its parent and children, and has a payload. 我使用的是通用树结构,其中每个节点都知道其父级和子级,并具有有效负载。
  • Classes: TreeBuilder , AbstractNode , VehicleNode , ColorNode , MakerNode , and another ordered list of enums which defines the order of the levels: BY_VEHICLE , BY_COLOR , BY_MAKER - you switch these around to get desired perspective 类: TreeBuilderAbstractNodeVehicleNodeColorNodeMakerNode以及另一个定义级别顺序的枚举的有序列表: BY_VEHICLEBY_COLORBY_MAKER您可以切换它们以获得所需的视角
  • Iterate through the list of enums, collecting ALL entities specific to that enum value (cars, makers, colors) as objects or so. 遍历枚举列表,收集所有特定于该枚举值的实体(汽车,制造商,颜色)作为对象。 With a factory method, create a node using the enumValue , while passing the tree builder, and the parentEnumValue (for a top-level, the parent enum value is NULL). 使用工厂方法,使用enumValue ,同时传递树构建器和parentEnumValue (对于顶级,父枚举值是NULL)来创建节点。
  • Child has a getParentMember_Internal which fetches the corect parent based on parentEnumValue (by using the treeBuilder which contains all the data mappings) 子级有一个getParentMember_Internal ,它基于parentEnumValue获取corect父parentEnumValue (通过使用包含所有数据映射的treeBuilder
  • In the previous iteration which I've mentioned, using the parent object of the resulting node, we can search through the tree and see which node it is (keep in mind levels are created top-down, so parents already exist) 在我提到的上一个迭代中,使用结果节点的父对象,我们可以搜索树并查看它是哪个节点(请记住,自上而下创建了各个级别,因此父级已经存在)

Why it doesn't work: 为什么不起作用:

  • When searching for the correct parent, there may be several instances of it in the tree, so we are forced to look at the grandparent as well. 在寻找正确的父母时,树中可能有几个实例,因此我们也不得不考虑祖父母。
  • Also, branches may be duplicated (see second tree) 另外,分支可能会重复(请参阅第二棵树)

What I'm asking: 我要问的是:

  • Is there a specific naming for this kinda of tree/algorithm? 这种树/算法是否有特定的命名? I couldn't think of an English term for this to use in Google. 我想不出一个英文字词来在Google中使用。
  • Does it have anything to do with a "KD Tree"? 它与“ KD树”有关系吗?
  • Is there a generic way to do this sort of thing? 有没有一种通用的方式来做这种事情?

EDIT 1 @Andreas 编辑1 @Andreas

There are only 3 possible entities in the tree: Vehicle , Color , Maker . 树中只有3种可能的实体: VehicleColorMaker There is not "vehicle type". 没有“车辆类型”。 All payloads in the tree are subclasses of these three. 树中的所有有效载荷都是这三个的子类。

I call them "payloads", because each object is wrapped in a AbstractNode subclass (which is part of a tree structure) to separate the data from the presentation layer. 我称它们为“有效载荷”,因为每个对象都包装在AbstractNode子类(树结构的一部分)中,以将数据与表示层分开。 Example: VehicleNode has a Vehicle payload . 示例: VehicleNode has a Vehicle payload

Since the entities are independent from eachother, levels may be hidden. 由于实体彼此独立 ,因此级别可能被隐藏。 This would be a valid case: 这是一个有效的情况:

|-- Green
|   |-- Audi
|   `-- BMW
|-- Blue
|   `-- Audi
|-- Red
|   |-- Audi
|   |-- BMW
|   `-- Honda
`-- Yellow
    |-- BMW (notice this doesn't appear twice under 'yellow', like in the second tree above)
    `-- Honda

In SQL, this is like a Star Schema , used in Data Warehouse databases for Online Analytical Processing (OLAP) . 在SQL中,这就像星形模式 ,已在数据仓库数据库中用于在线分析处理(OLAP)

In your case, that would be a Fact table Vehicle and 3 Dimensions ( Type , Brand , Color ). 在您的情况下,那将是一个事实表Vehicle和3个维度( TypeBrandColor )。

I'd suggest keeping the vehicles in a list, and build the 6 trees/indexes from the list, rather than trying to convert one tree to another. 我建议将车辆保留在列表中,并从列表中构建6棵树/索引,而不是尝试将一棵树转换为另一棵树。

A fully typed implementation might be to define a generic abstract tree: 一个完全类型化的实现可能是定义一个通用抽象树:

public abstract class Tree<F, D1, D2, D3> {
    protected Tree(List<F> facts) {
        // code here using getDimensionN() to build tree
    }
    protected abstract D1 getDimension1(F fact);
    protected abstract D2 getDimension2(F fact);
    protected abstract D3 getDimension3(F fact);
    public List<F> get(D1 dimension1) {
        // code here
    }
    public List<F> get(D1 dimension1, D2 dimension2) {
        // code here
    }
    public List<F> get(D1 dimension1, D2 dimension2, D3 dimension3) {
        // code here
    }
    // other public accessor methods here
}

You can then construct a particular tree using code like: 然后,您可以使用以下代码来构建特定的树:

List<F> facts = ...;
Tree<Vehicle, Type, Brand, Color> typeBrandColorTree = new Tree<Vehicle, Type, Brand, Color>(facts) {
    protected Type getDimension1(Vehicle vehicle) { return vehicle.getType(); }
    protected Brand getDimension2(Vehicle vehicle) { return vehicle.getBrand(); }
    protected Color getDimension3(Vehicle vehicle) { return vehicle.getColor(); }
};

// Use of tree
List<Vehicle> audiCars = typeBrandColorTree.get(Type.CAR, Brand.AUDI);

Update 更新资料

The Star Schema may not be appropriate for your particular question, so this is more for information about Star Schemas. 星型模式可能不适用于您的特定问题,因此更多有关星型模式的信息。 Let me use an example to illustrate what a Fact might be. 让我用一个例子来说明事实。

A fact could be the sale of a Vehicle, where the sale statistics being tracked includes: 一个事实可能是车辆的销售,其中跟踪的销售统计信息包括:

  • Type (Car, Bike) 类型(汽车,自行车)
  • Brand (Audi, BMW, Honda) 品牌(奥迪,宝马,本田)
  • Color (Green, Blue, Red, Yellow) 颜色(绿色,蓝色,红色,黄色)
  • Date 日期
  • Price 价钱

The trees/indexes can then be used to answer questions like: 然后,树/索引可用于回答以下问题:

  • Show sales of Audi Cars. 显示奥迪汽车的销售。
  • How many Blue Bikes were sold? 售出了多少辆蓝色自行车?
  • List total sales amount by Brand. 按品牌列出总销售额。

For faster access, the tree nodes could even have pre-aggregated values like Count and TotalPrice , such that you won't need to iterate all the facts to get your answers. 为了更快地访问,树节点甚至可以具有预先聚合的值,例如CountTotalPrice ,这样您就不需要遍历所有事实来获得答案。

This is mainly used for huge data sets (eg 10 years of national sales data), to help managers get various summary statistics on-demand, fast. 这主要用于大型数据集(如10周年全国的销售数据),以帮助管理者获得点播各种汇总统计,快捷。 Hence the term "Online Analytical Processing". 因此,术语“在线分析处理”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM