Php 在嵌套数组中查找内部数组
我在PHP中有一个嵌套数组:Php 在嵌套数组中查找内部数组,php,arrays,nested,Php,Arrays,Nested,我在PHP中有一个嵌套数组: array ( '0' => "+5x", '1' => array ( '0' => "+", '1' => "(", '2' => "+3", '3' => array ( '0' => "+", '1' => "(", '2' => array ( // I want
array (
'0' => "+5x",
'1' => array (
'0' => "+",
'1' => "(",
'2' => "+3",
'3' => array (
'0' => "+",
'1' => "(",
'2' => array ( // I want to find this one.
'0' => "+",
'1' => "(",
'2' => "+5",
'3' => "-3",
'4' => ")"
),
'3' => "-3",
'4' => ")"
),
'4' => ")"
)
);
我需要在这里处理最里面的数组,一个带有注释的数组:“我想找到这一个。”是否有一个函数用于此
我曾考虑过这样做(作为一个想法,而不是正确的PHP编写):
因此,它的作用是使$name
成为数组中的当前键。如果该值是一个数组,则它与foreach一起进入该数组,并添加“.”和数组的id。因此,在示例阵列中,我们将以:
array (
'0' => "1.3.2",
)
然后我可以处理这些值以访问Inner数组
问题是,我试图查找的内部数组是动态的,由用户输入组成。(它在找到+或-,的位置拆分输入字符串,如果包含方括号,则将其放入单独的嵌套数组中。因此,如果用户键入大量方括号,则将有大量嵌套数组。)
因此,我需要使这个模式向下运行20次,但不管发生什么情况,它仍然只能捕获20个嵌套数组
还有一个功能吗?或者有没有一种方法可以让它不用我的长代码就可以做到这一点?可能会制作一个循环,生成foreach模式的必要编号,并通过
eval()
?运行它。请尝试以下代码并告诉我结果
只需将数组传递给find\u
函数即可
function find_deepest( $array )
{
$index = ''; // this variable stores the current position (1.2, 1.3.2, etc.)
$include = true; // this variable indicates if the current position should be added in the result or not
$result = array(); // this is the result of the function, containing the deepest indexes
$array_stack = array(); // this is a STACK (or LIFO) to temporarily store the sub-arrays - see http://en.wikipedia.org/wiki/LIFO_%28computing%29
reset( $array ); // here we make the array internal POINTER move to the first position
// each loop interaction moves the $array internal pointer one step forward - see http://php.net/each
// if $current value is null, we reached the end of $array; in this case, we will also continue the loop, if the stack contains more than one array
while ( ( $current = each( $array ) ) || ( count( $array_stack ) > 1 ) )
{
// we are looping $array elements... if we find an array (a sub-array), then we will "enter it...
if ( is_array( $current['value'] ) )
{
// update the index string
$index .= ( empty ( $index ) ? '' : '.' ) . $current['key'];
// we are entering a sub-array; by default, we will include it
$include = true;
// we will store our current $array in the stack, so we can move BACK to it later
array_push( $array_stack, $array );
// ATTENTION! Here we CHANGE the $array we are looping; here we "enter" the sub-array!
// with the command below, we start to LOOP the sub-array (whichever level it is)
$array = $current['value'];
}
// this condition means we reached the END of a sub-array (because in this case "each()" function has returned NULL)
// we will "move out" of it; we will return to the previous level
elseif ( empty( $current ) )
{
// if we reached this point and $include is still true, it means that the current array has NO sub-arrays inside it (otherwise, $include would be false, due to the following lines)
if ( $include )
$result[] = $index;
// ATTENTION! With the command below, we RESTORE $array to its precedent level... we entered a sub-array before, now we are goin OUT the sub-array and returning to the previous level, where the interrupted loop will continue
$array = array_pop( $array_stack );
// doing the same thing with the $index string (returning one level UP)
$index = substr( $index, 0, strrpos( $index, '.' ) );
// if we are RETURNING one level up, so we do NOT want the precedent array to be included in the results... do we?
$include = false;
}
// try removing the comment from the following two lines! you will see the array contents, because we always enter this "else" if we are not entering a sub-array or moving out of it
// else
// echo $index . ' => ' . $current['value'] . '<br>';
}
return $result;
}
$result = find_deepest( $my_array );
print_r( $result );
函数查找($array)
{
$index='';//此变量存储当前位置(1.2、1.3.2等)
$include=true;//此变量指示是否应在结果中添加当前位置
$result=array();//这是函数的结果,包含最深的索引
$array_stack=array();//这是一个临时存储子数组的堆栈(或LIFO)-请参阅http://en.wikipedia.org/wiki/LIFO_%28computing%29
reset($array);//这里我们将数组内部指针移动到第一个位置
//每个循环交互都会将$array内部指针向前移动一步-请参阅http://php.net/each
//如果$current值为null,则到达$array的末尾;在本例中,如果堆栈包含多个数组,则还将继续循环
而(($current=each($array))| |(count($array_stack)>1))
{
//我们正在循环$array元素…如果我们找到一个数组(子数组),那么我们将“输入它…”。。。
if(是_数组($current['value']))
{
//更新索引字符串
$index.=(空($index)“:”).$current['key'];
//我们正在输入一个子数组;默认情况下,我们将包含它
$include=true;
//我们将把当前的$数组存储在堆栈中,以便以后可以返回到它
array\u push($array\u stack,$array);
//注意!我们在这里更改正在循环的$数组;在这里“输入”子数组!
//使用下面的命令,我们开始循环子数组(无论它是哪个级别)
$array=$current['value'];
}
//这个条件意味着我们到达了子数组的末尾(因为在本例中“each()”函数返回NULL)
//我们将“走出”它;我们将回到以前的水平
elseif(空($当前))
{
//如果我们达到这一点,$include仍然为true,则表示当前数组中没有子数组(否则,$include将为false,原因如下所示)
若有($包括)
$result[]=$index;
//注意!使用下面的命令,我们将$array恢复到它以前的级别…我们之前输入了一个子数组,现在我们将退出子数组并返回到上一级别,在那里中断的循环将继续
$array=array\u pop($array\u stack);
//对$index字符串执行相同的操作(返回一级)
$index=substr($index,0,strrpos($index,'.');
//如果我们返回一个级别,那么我们不希望在结果中包含先例数组…是吗?
$include=false;
}
//尝试从下面两行中删除注释!您将看到数组内容,因为如果不输入子数组或移出子数组,我们总是输入此“else”
//否则
//回显$index.'=>'.$current['value'].
';
}
返回$result;
}
$result=find_deep($my_数组);
打印(结果);
守则最重要的部分包括:
while
循环中的每个
命令array\u push
函数调用,我们将当前数组存储在“数组堆栈”中,以便稍后返回array\u pop
函数调用,通过从“数组堆栈”还原当前数组返回一级RecursiveIteratorIterator
知道所有子项的当前深度。由于您只对有子项的子项感兴趣,请筛选出没有子项的子项并查找最大深度
然后根据深度再次过滤最大深度:
$ritit = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr), RecursiveIteratorIterator::SELF_FIRST);
$cf = new ChildrenFilter($ritit);
$maxdepth = NULL;
foreach($cf as $v)
{
$maxdepth = max($maxdepth, $cf->getDepth());
}
if (NULL === $maxdepth)
{
throw new Exception('No children found.');
}
$df = new DepthFilter($cf, $maxdepth);
foreach($df as $v)
{
echo "Array with highest depth:\n", var_dump($v), "\n";
}
/递归foreach函数,来自以下注释: 请注意,上述实现会生成一个扁平阵列。要保留嵌套,请执行以下操作:
function RecurseArray($inarray) {
$result = array();
foreach ( $inarray as $inkey => $inval ) {
if ( is_array($inval) ) {
$result[] = RecurseArray($inval);
} else {
// process $inval, store in result array
$result[] = $inval;
}
}
return $result;
}
要在位修改阵列,请执行以下操作:
function RecurseArray(&$inarray) {
foreach ( $inarray as $inkey => &$inval ) {
if ( is_array($inval) ) {
RecurseArray($inval);
} else {
// process $inval
...
}
}
}
定义
简单:
描述没有子表达式的表达式(例如“5”、“x”)。
化合物:
描述具有子表达式的表达式(例如“3+x”、“1+2”)。
常数:
表达式是否具有常量值(例如“5”、“1+2”)(例如“x”、“3+x”)。
外部节点:
在表达式树中,通过始终向左或向右遍历可到达的节点。“外部”始终相对于给定节点;节点可能相对于一个节点“外部”,但相对于该节点的父节点“内部”。
内部节点:function RecurseArray($inarray) {
$result = array();
foreach ( $inarray as $inkey => $inval ) {
if ( is_array($inval) ) {
$result[] = RecurseArray($inval);
} else {
// process $inval, store in result array
$result[] = $inval;
}
}
return $result;
}
function RecurseArray(&$inarray) {
foreach ( $inarray as $inkey => &$inval ) {
if ( is_array($inval) ) {
RecurseArray($inval);
} else {
// process $inval
...
}
}
}
__1__
/ \
2 5
/ \ / \
3 4 6 7
array(
'=' => array(
'+' => array( // 5x + 3
'*' => array(
5, 'x'
),
3
)
'+' => array( // (x+(3+(5-3)))
'x',
'+' => array( // (3+(5-3))
3,
'-' => array(
5, 3
) ) ) ) )
array(
'=' => array(
'+' => array( // 5x + 3
'*' => array(
5, 'x'
),
3
)
'+' => array( // x+3+5-3
'x',
3,
'-' => array(
5, 3
) ) ) )
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;
+ + + +
/ \ / \ / \ / \
\+ 2 ---> + 2 + y ---> + y
/ \ / \ / \ / \
1 x x 1 x 1 1 x
+ +
/ \ / \
\+ c ---> a +
/ \ / \
a b b c
Expression
/ \
SimpleExpr CompoundExpr
/ \
ConstantExpr VariableExpr
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
}
}
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;
}
}
}
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;
}
}