PHP中数组嵌套,php – 在嵌套数组中查找内部数组

定义

简单:

描述没有子表达式的表达式(例如“5”,“x”).

复合:

描述具有子表达式的表达式(例如“3 x”,“1 2”).

常量性:

表达式是否具有恒定值(例如“5”,“1 2”)或不具有(例如“x”,“3 x”).

外节点:

在表达式树中,通过始终遍历左或始终遍历右侧可到达的节点. “外”总是相对于给定节点;节点可能相对于一个节点是“外部”,但相对于该节点的父节点是“内部”.

内节点:

在表达式树中,不是外部节点的节点.

有关“内部”和“外部”节点的说明,请考虑:

__1__

/ \

2 5

/ \ / \

3 4 6 7

3和7总是外部节点. 6是相对于5的外部,但是相对于1的内部.

回答

这里的困难更多地在于表达格式不均匀而不是嵌套.如果使用表达式树,示例5x 3 =(x(3(5-3)))等式将解析为:

array(

'=' => array(

'+' => array( // 5x + 3

'*' => array(

5, 'x'

),

3

)

'+' => array( // (x+(3+(5-3)))

'x',

'+' => array( // (3+(5-3))

3,

'-' => array(

5, 3

) ) ) ) )

请注意,二进制操作的节点是二进制的,并且一元操作将具有一元节点.如果二进制可交换操作的节点可以组合成n-ary节点,则可以将5x 3 = x 3 5-3解析为:

array(

'=' => array(

'+' => array( // 5x + 3

'*' => array(

5, 'x'

),

3

)

'+' => array( // x+3+5-3

'x',

3,

'-' => array(

5, 3

) ) ) )

然后,您将编写一个可以简化节点的后序递归函数. “后序”意味着节点处理在处理其子节点之后发生;还有预订(在其子节点之前处理节点)和按顺序(在节点之前处理一些子节点,之后处理其余子节点).以下是粗略概述.其中,“thing:Type”表示“thing”的类型为“Type”,“&”表示按引用传递.

simplify_expr(expression : Expression&, operation : Token) : Expression {

if (is_array(expression)) {

foreach expression as key => child {

Replace child with simplify_expr(child, key);

key will also need to be replaced if new child is a constant

and old was not.

}

return simplify_node(expression, operation);

} else {

return expression;

}

}

simplify_node(expression : Expression&, operation : Token) : Expression;

在某种程度上,真正的挑战是编写simplify_node.它可以在表达式节点上执行许多操作:

>如果一个内在的大孩子与另一个孩子的常数不匹配,但是它的兄弟姐妹那个,交换兄弟姐妹.换句话说,将奇数输出作为外部节点.这一步是为下一步做准备.

+ + + +

/ \ / \ / \ / \

\+ 2 ---> + 2 + y ---> + y

/ \ / \ / \ / \

1 x x 1 x 1 1 x

>如果节点和子节点是相同的可交换操作,则可以重新排列节点.例如,有旋转:

+ +

/ \ / \

\+ c ---> a +

/ \ / \

a b b c

这对应于将“(a b)c”改变为“a(b c)”.当“a”与“b”和“c”的常量不匹配时,您将要旋转.它允许将下一个转换应用于树.例如,此步骤将“(x 3)1”转换为“x(3 1)”,因此下一步可将其转换为“x 4”.

总体目标是将const子树作为兄弟姐妹.如果一个可交换节点有两个const后代,它们可以相互旋转.如果一个节点只有一个const后代,那么让它成为一个子节点,这样层次结构中的一个节点可以将const节点与另一个祖先的const子节点组合起来(即const节点浮动直到它们是兄弟节点,此时它们像苏打水中的气泡一样结合在一起.

>如果所有子节点都是常量,请评估节点并将其替换为结果.

处理具有多个复合子节点和n-ary节点的节点作为读者的练习.

面向对象的替代方案

OO方法(使用对象而不是数组来构建表达式树)将具有许多优点.操作将与节点关联得更紧密;它们是节点对象的属性,而不是节点键.将辅助数据与表达式节点相关联也会更容易,这对优化很有用.您可能不需要深入了解OOP范例来实现它.可以使用以下简单类型层次结构:

Expression

/ \

SimpleExpr CompoundExpr

/ \

ConstantExpr VariableExpr

操纵树的现有自由函数将成为方法.接口看起来像下面的伪代码.在里面:

>儿童< Parent表示“Child”是“Parent”的子类.

>属性(如isConstant)可以是方法或字段;在PHP中,您可以使用overloading实现此功能.

>(…){…}表示函数,括号和括号之间的参数之间的参数(很像Javascript中的函数(…){…}).此语法用于作为方法的属性.简单方法只是使用方括号的括号.

现在为样本:

Expression {

isConstant:Boolean

simplify():Expression

}

SimpleExpr < Expression {

value:Varies

/* simplify() returns an expression so that an expression of one type can

be replaced with an expression of another type. An alternative is

to use the envelope/letter pattern:

http://users.rcn.com/jcoplien/Patterns/C++Idioms/EuroPLoP98.html#EnvelopeLetter

http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Envelope_Letter

*/

simplify():Expression { return this }

}

ConstantExpr < SimpleExpr {

isConstant:Boolean = true

}

VariableExpr < SimpleExpr {

isConstant:Boolean = false

}

CompoundExpr < Expression {

operation:Token

children:Expression[]

commutesWith(op:Expression):Boolean

isCommutative:Boolean

isConstant:Boolean = (){

for each child in this.children:

if not child.isConstant, return false

return true

}

simplify():Expression {

for each child& in this.children {

child = child.simplify()

}

return this.simplify_node()

}

simplify_node(): Expression {

if this.isConstant {

evaluate this, returning new ConstExpr

} else {

if one child is simple {

if this.commutesWith(compound child)

and one grand-child doesn't match the constness of the simple child

and the other grand-child matches the constness of the simple child

{

if (compound child.isCommutative):

make odd-man-out among grand-children the outer child

rotate so that grand-children are both const or not

if grand-children are const:

set compound child to compound child.simplify_node()

}

} else {

...

}

}

return this

}

}

例如,SimpleExpr和ConstantExpr的PHP实现可以是:

class SimpleExpr extends Expression {

public $value;

function __construct($value) {

$this->value = $value;

}

function simplify() {

return $this;

}

}

class ConstantExpr extends SimpleExpr {

// Overloading

function __get($name) {

switch ($name) {

case 'isConstant':

return True;

}

}

}

ConstantExpr的替代实现:

function Expression {

protected $_properties = array();

// Overloading

function __get($name) {

if (isset($this->_properties[$name])) {

return $this->_properties[$name];

} else {

// handle undefined property

...

}

}

...

}

class ConstantExpr extends SimpleExpr {

function __construct($value) {

parent::construct($value);

$this->_properties['isConstant'] = True;

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值