【问题标题】:Find parent keys in hierarchy in PHP在 PHP 中查找层次结构中的父键
【发布时间】:2016-12-16 11:50:25
【问题描述】:

我有以下Array 结构$array

Array
  (
       [WIDGET_BUILDER_CREATE] => Array
       (
        [TITLE] => Widget Builder
        [WIDGET_TYPE_LBL] => Select Widget Type
        [RANGE_LBL] => Select Range
        [RANGE_TYPE_LBL] => Select Range Type
        [TOP_SERVICE_CHKBOX] => Top Services
        [SR_STATE_LBL] => Select Sr States
        [SR_TYPE_LBL] => Select Sr Types
        [SR_CATEGORY_LBL] => Select Sr Categories
        [SR_SOURCE_LBL] => Select Sources
        [SR_PROVIDER_LBL] => Select Sr Provider
        [ADDRESS] => Enter Address
        [SUBMIT_BTN] => Generate Data
        [CHART_DIV] => Array
            (
                [TYPE] => Select chart type
                [SAVE_BTN] => Save Widget
                [SERIES_NAME] => Change Parameters
                [PARA_DIALOG] => Array
                    (
                        [TITLE] => Chart Parameters
                        [SERIESNAME] => Series Name
                        [YAXISNAME] => Y axies name
                        [VALIDATION] => Array
                            (
                                [SERIESNAME] => Please enter series name
                                [YAXISNAME] => Please enter y axis name
                            )

                        [SAVE_BTN] => Save
                        [CANCEL_BTN] => Cancel
                    )

                [SAVE_DIALOG] => Array
                    (
                        [TITLE] => Save Chart
                        [CHART_NAME] => Chart Name
                        [SHOW_TO_USER] => System Widget
                        [VALIDATION] => Array
                            (
                                [CHART_NAME] => Please enter chart name
                            )

                        [SAVE_BTN] => Save
                        [CANCEL_BTN] => Cancel
                    )

            )

        [GRID_DIV] => Array
            (
            )

    )

  )

问题:

我想在 PHP 中构建一个函数,如果我输入一个值,那么它应该返回层次结构中的所有父键。

例如,如果我输入Please enter y axis name,它应该返回为

$array['WIDGET_BUILDER_CREATE']['CHART_DIV']['PARA_DIALOG']['VALIDATION']['YAXISNAME'];

编辑: 我尝试过How to get hierarchy path of an element in an Array,但它作为字符串返回,但我希望作为数组键索引。这意味着

print_r($array['WIDGET_BUILDER_CREATE']['CHART_DIV']['PARA_DIALOG']['VALIDATION']['YAXISNAME']);

//returns Please enter y axis name

我使用的是 PHP 5.5.9

【问题讨论】:

  • 我不明白。该函数应该返回您输入的相同值吗?在您的示例中,$array['WIDGET_BUILDER_CREATE']... 实际上会返回字符串 "Please enter y axis name"
  • 我认为张贴者希望函数返回包含字符串而不是值的数组路径。
  • 如果相同的文本在数组中出现两次怎么办?
  • @Daan ,这是可能的,但会在不同的键内
  • 那你想得到哪条路径作为回报呢?两者都有?

标签: php arrays key key-value


【解决方案1】:

如果您觉得可以使用快速而肮脏的方法,您可能想尝试下面的function,它使用嵌套的foreach 循环。但是,如果您觉得很怪异,您可以简单地自己重构嵌套循环并将它们变成更短的递归算法。要测试这个 Quick & Dirty 方法,请转到 here

样本数据:

<?php

    $array = [
        'WIDGET_BUILDER_CREATE' => [
            "TITLE"                 => "Widget Builder",
            "WIDGET_TYPE_LBL"       => "Select Widget Type",
            "RANGE_LBL"             => "Select Range",
            "RANGE_TYPE_LBL"        => "Select Range Type",
            "TOP_SERVICE_CHKBOX"    => "Top Services",
            "SR_STATE_LBL"          => "Select Sr States",
            "SR_TYPE_LBL"           => "Select Sr Types",
            "SR_CATEGORY_LBL"       => "Select Sr Categories",
            "SR_SOURCE_LBL"         => "Select Sources",
            "SR_PROVIDER_LBL"       => "Select Sr Provider",
            "ADDRESS"               => "Enter Address",
            "SUBMIT_BTN"            => "Generate Data",
            "CHART_DIV"             => [
                "TYPE"          => "Select chart type",
                "SAVE_BTN"      => "Save Widget",
                "SERIES_NAME"   => "Change Parameters",
                "PARA_DIALOG"   => [
                    "TITLE"         => "Chart Parameters",
                    "SERIESNAME"    => "Series Name",
                    "YAXISNAME"     => "Y axies name",
                    "VALIDATION"    => [
                        "SERIESNAME"    => "Please enter series name",
                        "YAXISNAME"     => "Please enter y axis name",

                    ],
                    "SAVE_BTN"          => "Save",
                    "CANCEL_BTN"        => "Cancel",
                ],
                "SAVE_DIALOG"   =>[
                    "TITLE"         => "Save Chart",
                    "CHART_NAME"    => "Chart Name",
                    "SHOW_TO_USER"  => "System Widget",
                    "VALIDATION"    => [
                        "CHART_NAME"    => "Please enter chart name",
                    ],
                    "SAVE_BTN"      => "Save",
                    "CANCEL_BTN"    => "Cancel",
                ],

            ],
            "GRID_DIV"              => [],
        ],
    ];

快速而肮脏的功能:

<?php

    function keywordLookUp(array $array, $keyWord, $arrayName="\$array"){
        $route   = $mainKey   = null; $arrRte   = $arrResult   = [];
        foreach($array as $intKey=>$item){
            $mainKey =  $route = "{$arrayName}['{$intKey}']";
            if(is_array($item)){
                foreach($item as $iKey=>$innerItem){
                    if($lKey = array_search($keyWord, $item)){
                        $route .=  $s = "['$lKey']"; break;
                    }
                    if(is_array($innerItem)){
                        foreach($innerItem as $iKey2=>$innerItem2){
                            if($lKey = array_search($keyWord, $innerItem)){
                                if(isset($s)){
                                if(! array_search($route, $arrRte)){$arrRte[] = $route;}
                                    $arrRte[] =  "{$s}['$lKey']";
                                    $route .=  "\n{$s}['$lKey']";
                                }else{
                                    $route .=  "['$iKey']['$lKey']";
                                }   $s      =  str_replace("['$lKey']", "", $route); break;
                            }
                            if(is_array($innerItem2)){
                                foreach($innerItem2 as $iKey3=>$innerItem3){
                                    if($lKey = array_search($keyWord, $innerItem2)){
                                        if(isset($s)){
                                            if(! array_search($route, $arrRte)){$arrRte[] = $route;}
                                            $arrRte[] ="{$s}['$iKey2']['$lKey']";
                                            $route .=  "\n{$s}['$iKey2']['$lKey']";
                                        }else{
                                            $route .=  "['$iKey']['$iKey2']['$lKey']";
                                        }   $s      =  str_replace("['$iKey2']['$lKey']", "", $route); break;
                                    }
                                    if(is_array($innerItem3)){
                                        foreach($innerItem3 as $iKey4=>$innerItem4){
                                            if($lKey = array_search($keyWord, $innerItem3)){
                                                if(isset($s)){
                                                    if(! array_search($route, $arrRte)){$arrRte[] = $route;}
                                                    $arrRte[] = "{$s}['$iKey3']['$lKey']";
                                                    $route .=  "\n{$s}['$iKey3']['$lKey']";
                                                }else{
                                                    $route .=  "['$iKey']['$iKey2']['$iKey3']['$lKey']";
                                                }break;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        $fin = ($route == $mainKey) ? null : $route;
        $fin = (!empty($arrRte) && sizeof($arrRte > 1))?$arrRte:$fin;
        return $fin;
    }

    $path  = keywordLookUp($array, "Please enter y axis name");
    $path2 = keywordLookUp($array, "Chart Parameters");
    $path3 = keywordLookUp($array, "Cancel");

    var_dump($path);
    // PRODUCES::  string '$array['WIDGET_BUILDER_CREATE']['CHART_DIV']['PARA_DIALOG']['VALIDATION']['SERIESNAME']' (length=87)

    var_dump($path2);
    // PRODUCES::  string '$array['WIDGET_BUILDER_CREATE']['CHART_DIV']['PARA_DIALOG']['TITLE']' (length=68)

    var_dump($path3);
    // PRODUCES:: 
    array (size=2)
      0 => string '$array['WIDGET_BUILDER_CREATE']['CHART_DIV']['PARA_DIALOG']['CANCEL_BTN']' (length=73)
      1 => string '$array['WIDGET_BUILDER_CREATE']['CHART_DIV']['SAVE_DIALOG']['CANCEL_BTN']' (length=73)

【讨论】:

  • 该解决方案不包括顶级密钥。它也不支持深度嵌套的数组,因为您对深度进行了硬编码。最后,OP 说如果有多个匹配的路径,该函数应该返回一个包含所有这些路径的数组,这不会。不过,这是一种有趣的方法。
  • @BeetleJuice 非常感谢您指出这一点,但我认为您也应该注意以下几点:Quick & Dirty如果你觉得怪怪的,你可以简单地自己重构嵌套循环并将它们变成更短的递归算法。是的,它不支持深度嵌套结构,这就是我提到的原因,OP 被要求实现的递归算法......但是,谢谢......
  • @Hiranya 当然...帖子刚刚更新为包含...如果您的数组超过 4 个级别,建议您考虑实施递归算法...
  • @Poiz 我确实读过你的帖子。我决定发表评论,因为即使作为一种快速而肮脏的解决方案,由于我指出的其他原因,它也没有返回正确的答案。相对于其他原因,深度并不是什么大问题。我不是故意冒犯(对不起,如果我冒犯了)。
  • @BeetleJuice 只有当你所说的不包含真理时才会被冒犯......如果你的观点显然是正确的,为什么要被冒犯?也许,写作语气不正确,但老实说,没有冒犯甚至感觉......并且已经证实;你是对的...... ;-)
【解决方案2】:

下面的函数搜索$source 数组并返回一个数组,其中包含$target 值的所有匹配路径。如果在$source 中找不到该值,则返回一个空数组。

function pathFinder($target, array $source, $parentPath=''){
    $results=[];
    foreach($source as $k => $v){
        $path = $parentPath.'/'.$k; //current path
        //if element is array, recurse and import found results
        if(is_array($v) && $result=pathFinder($target, $v,$path)){
            foreach($result as $r) array_push($results,$r);
        }
        //else add element to results if it matches $target
        elseif($v===$target) $results[]=$path;     
    }
    return $results;
}

用法:

$target = 'Please enter axis Y name';
$foundPaths = pathFinder($target, $array);

Live demo

【讨论】:

  • 它返回/WIDGET_BUILDER_CREATE/CHART_DIV/PARA_DIALOG/VALIDATION/YAXISNAME,但不是array index
  • @Hiranya 所以我为你做了最困难的部分。当然,你可以做剩下的。只需在$path = $parentPath.'/'.$k; 行上工作即可根据需要格式化路径。或者只是通过执行explode('/',$result) 格式化函数返回的路径,然后在每个结果周围添加括号[]。如果您选择使用我的答案作为您的解决方案的基础,请不要忘记投票并选择它。
猜你喜欢
  • 2021-09-29
  • 1970-01-01
  • 2013-01-21
  • 2017-05-15
  • 2021-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多