`
k_lb
  • 浏览: 822188 次
  • 性别: Icon_minigender_1
  • 来自: 郑州
社区版块
存档分类
最新评论
  • kitleer: 据我所知,国内有款ETL调度监控工具TaskCTL,支持ket ...
    kettle调度

递归分解 - Fastm Match Engine

 
阅读更多

应一位程序员朋友要求,写了这篇fastm engine内部实现原理的技术文档。

递归分解-- Fastm Match Engine

Matching Rule

Fastm Template是一个树形结构。Dynamic下面包含Static Text, Variable, Dynamic三种节点。

Fastm Template里面除了静态文本,动态部分只有两类,Dynamic Block Variable

Fastm Template DOM + Data的匹配过程,很类似于XSLPattern Match的递归组合。

Match ( Template Node, Current Data) {

Switch(Template Node)

Case Static Text: 直接显示

Case Variable: 当前数据层根据Variable名称获取数据并显示

Case Dynamic: 当前数据层根据Dynamic名称获取数据(下一层子数据),作为当前数据层,并且展开并且一个一个遍历当前数据,对于每一个数据项,Dynamic向下走一层开始一个个遍历所有孩子节点

(注意,这一步没有显示动作,只有非常复杂的数据展开和模板展开的动作。并进行n * m匹配的逻辑。n是数据子项的个数,mDynamic孩子的个数)

}

注意,重中之重。

当前数据层根据Dynamic名称获取数据(下一层子数据),作为当前数据层,并且展开并且一个一个遍历当前数据,对于每一个数据项,Dynamic向下走一层开始一个个遍历所有孩子节点

这是整个匹配过程中,最核心的动作。这是理解整个匹配引擎的关键。

注意,这是3步动作。

第一步动作,遇到Dynamic,根据Dynamic Name从当前数据层,获取属性(子数据),然后把这个子数据作为当前数据。

第二步动作,就把子数据作为当前的数据展开:如果是Array, Collection,就一个一个展开。

第三步动作,对于其中每一个数据项,Dynamic的所有孩子都和分别这个数据项进行匹配。

这可以看作是两重循环。

Case Dynamic:

Property = get Property From (Current Data, Dynamic Name)

Current Data = Property

for each Item in the Current Data { // Current Data may be an array, a collection, etc

for each Template Node in the Current Dynamic Node {

match (Template Node, Item); // 递归调用Match

}

}

好了,我们来看整个递归过程。

Match ( Template Node, Current Data) {

Switch(Template Node)

Case Static Text: 直接显示

Case Variable: 当前数据层根据Variable名称获取数据并显示

Case Dynamic:

Property = get Property From (Current Data, Dynamic Name)

Current Data = Property

for each Item in the Current Data { // Current Data may be an array, a collection, etc

for each Template Node in the Current Dynamic Node {

match (Template Node, Item); // 递归调用Match

}

}

}

简化起来看起来是这样。

Match(){

.. Match();

}

自己调用自己,形成了递归。

递归步骤分解

f() {

..f()..

}

叫做递归。

f() {

..g()..

}

g(){

f()

}

也叫做递归。所不同的只是,分成了2个函数。

f() {

..g()..

}

g(){

h()

}

h() {

..f()..

}

也叫做递归。所不同的只是,分成了3个函数。

我们把上面的Match ()分解。

分解步骤1:分出forEachDataItem

Match ( Template Node, Current Data) {

Switch(Template Node)

Case Static Text: 直接显示

Case Variable: 当前数据层根据Variable名称获取数据并显示

Case Dynamic:

Property = get Property From (Current Data, Dynamic Name)

Current Data = Property

forEachDataItem(Current Dynamic Node, Current Data);

}

forEachDataItem(DynamicNode, Current Data){

for each Item in the Current Data { // Current Data may be an array, a collection, etc

for each Template Node in the Current Dynamic Node {

match (Template Node, Item); // 递归调用Match

}

}

}

现在的递归关系是

Match{

.. forEachDataItem()..

}

forEachDataItem{

..Match()..

}

分解步骤2:分出forEachDynamicChild

Match ( Template Node, Current Data) {

Switch(Template Node)

Case Static Text: 直接显示

Case Variable: 当前数据层根据Variable名称获取数据并显示

Case Dynamic:

Property = get Property From (Current Data, Dynamic Name)

Current Data = Property

forEachDataItem(Current Dynamic Node, Current Data);

}

forEachDataItem(DynamicNode, Current Data){

for each Item in the Current Data { // Current Data may be an array, a collection, etc

forEachDynamicChildren(Dynamic Node, Item);

}

}

forEachDynamicChildren(Dynamic Node, Current Data){

for each Template Node in the Current Dynamic Node {

match (Template Node, Item); // 递归调用Match

}

}

现在的递归关系变成,

Match{

.. forEachDataItem()..

}

forEachDataItem{

..forEachDynamicChildren()..

}

forEachDynamicChildren{

..Match()..

}

递归步骤合并

递归步骤既然可以分解,自然可以合并。

我们把forEachDynamicChildren Match合并。

forEachDataItem(DynamicNode, Current Data){

for each Item in the Current Data { // Current Data may be an array, a collection, etc

forEachDynamicChildren(Dynamic Node, Item);

}

}

forEachDynamicChildren(Dynamic Node, Current Data){

for each Template Node in the Current Dynamic Node {

Switch(Template Node)

Case Static Text: 直接显示

Case Variable: 当前数据层根据Variable名称获取数据并显示

Case Dynamic:

Property = get Property From (Current Data, Dynamic Name)

Current Data = Property

forEachDataItem(Current Dynamic Node, Current Data);

}

}

现在的递归调用关系就变成

forEachDataItem{

..forEachDynamicChildren()..

}

forEachDynamicChildren{

.. forEachDataItem ()..

}

为什么我最后保留了这种递归形势。

首先是为了保证两层循环分别在不同的两个函数里面。其次为了尽量减少递归函数的个数。

数据分支代表逻辑分支

Fastm Template为什么不需要逻辑分支?

Fastm利用数据分支来表示逻辑分支。

0个数据,表示不显示当前Dynamic Block。(if false

1个数据,表示显示当前Dynamic Block(if true)

n个数据,重复n次表示显示当前Dynamic Block(for, while).

这种分支动作只发生在Dynamic Block上面。

这里是理解的关键。

Case Dynamic:

Property = get Property From (Current DataDynamic Name)

Current Data = Property

forEachDataItem(Current Dynamic Node, Current Data);

程序根据Dynamic Name获取Property

如果获取的Property为空(Null or Empty),forEachDataImte就什么都不做。这就相当于不显示当前分支;如果Property里面只有一个元素(或者Property不是集合或者数组类型,那么元素就是Property本身),就显示一次;如果Property里面有n > 1)个元素(Property是元素个数为n的集合或者数组),那么就显示n次。

分享到:
评论

相关推荐

    递归-----动态树实现递归

    标题“递归-----动态树实现递归”暗示我们将探讨如何利用递归方法来操作动态树。 首先,让我们理解什么是动态树。动态树,顾名思义,是一种可以随程序运行而改变结构的树形数据结构。与静态树不同,它的节点可以在...

    java-c语法7---method-递归---马克-to-win java视频

    java语法 method 递归 马克-to-win java视频 方法 重载

    数据结构:栈与递归--含分治与回溯.ppt

    数据结构:栈与递归--含分治与回溯.ppt

    计算器递归----c++

    - **递归的应用场景**:对于含有括号的复杂表达式,递归可以有效地分解问题,先计算最内层括号内的表达式,然后逐步向外扩展,最终得到整个表达式的值。 ##### 2. **C++基础语法** - **头文件的引入**:`#...

    栈与递归--含分治与回溯.zip

    本资料“栈与递归--含分治与回溯”深入探讨了这两个主题,并将它们与分治策略和回溯法相结合,提供了一种高效解决问题的方法。 首先,栈是一种特殊的线性数据结构,遵循后进先出(LIFO)的原则。在计算机程序中,栈...

    递归分治-1-阶乘.cpp

    递归分治-1-阶乘.cpp

    递归2-2.py

    递归2-2.py

    json-rules-engine:以JSON表示的规则引擎

    json-rules-engine是功能强大的轻量级规则引擎。 规则由简单的json结构组成,使其易于阅读且易于持久。 产品特点 以简单易读的JSON表示的规则 完全支持ALL和ANY布尔运算符,包括递归嵌套 默认情况下为快速,通过配置...

    汉诺塔递归算法--C语言

    该问题可以分解为以下三个步骤: 1. 将n-1个圆盘从t1移动到t3(使用t2作为辅助):`move(n-1, t1, t3, t2)` 2. 将最大的圆盘从t1移动到t2 3. 将n-1个圆盘从t3移动到t2(使用t1作为辅助):`move(n-1, t3, t2, t1)` ...

    栈与递归--含分治与回溯.ppt

    递归关系则是指如何将大问题分解为更小的相似问题,然后用递归方式解决这些小问题。 例如,阶乘的计算可以使用递归来实现: ```cpp int factorial(int n) { if (n == 1) // 边界条件 return 1; else return n *...

    数据结构(c语言)---递归---Hanno.cpp

    数据结构(c语言) 对于汉诺塔的递归实现。在对学习数据结构递归的人,帮助他们对汉诺塔和递归思想的理解

    turtle-递归美学-分形树-draw_branch.rar

    在这个名为“turtle-递归美学-分形树-draw_branch.rar”的压缩包中,我们找到了一个名为`draw_branch.py`的文件,它展示了如何利用递归技术来创建美丽的分形树。分形是一种具有自相似性的几何形状,即无论在大尺度...

    C递归算法-八皇后问题.doc

    递归算法是一种解决问题的方法,它通过将问题分解成更小的子问题,直到找到解决方法为止。递归算法可以解决许多复杂的问题,如八皇后问题。 2. C语言的应用 C语言是一种广泛应用的编程语言,本文档展示了如何使用...

    树结点递归添加-VB.NET

    在VB.NET编程中,"树结点递归添加"是一个常见的操作,特别是在构建类似资源管理器的界面或处理文件系统目录结构时。递归是一种强大的编程技术,它允许函数调用自身来解决复杂的问题,特别适合处理具有层级关系的数据...

    递归--移盘子.png

    帮助新手理解C语言下移盘子问题,即Hanoi(汉诺)塔问题,更有助于新手对于C语言中对于递归函数的理解,强化程序逻辑问题。

    n后问题---递归回溯法 n后问题---递归回溯法

    n后问题---递归回溯法 n后问题---递归回溯法 n后问题---递归回溯法 n后问题---递归回溯法 n后问题---递归回溯法 n后问题---递归回溯法 n后问题---递归回溯法 n后问题---递归回溯法 n后问题---递归回溯法 n后问题---...

    第6章 函数和递归(C++版) 第二节 递归算法-2021-01-25(B).pdf

    递归的概念基于函数调用自身的能力,这种自引用的过程可以解决一些复杂的问题,将它们分解为更小、更易于处理的部分。 在C++中,递归分为直接递归和间接递归。直接递归是指一个函数在其定义中直接调用自身,例如,...

    实验2 递归算法-源代码.rar

    递归情况则是将问题继续分解,直到达到基本情况为止。 1. **螺旋矩阵**: 螺旋矩阵是一种特殊的矩阵排列方式,元素按顺时针方向从外向内排列。在C++中,可以使用递归方法实现。首先,我们需要确定矩阵的边界条件,...

Global site tag (gtag.js) - Google Analytics