我一直在努力编写一些优雅的代码,当给定子索引时将返回PHP数组的父索引。也许通过例子可以最好地说明这一点。下面是一个多维数组:
$array = array(
'Level 1a' => array(
'Level 2a' => array(
'Level 3a' => array(
'Level 4a' => array(
)
)
),
),
'Level 1b' => array(
'Level 2b' => array(
'Level 3b' => array(
'Level 4b' => array(
'Level 5b' => array()
)
)
),
),
'Level 1c' => array(
'Level 2c' => array(
'Level 3c' => array(
'Level 4c' => array(
)
)
),
'Level 2d' => array(
'Level 3e' => array(
'Level 4e' => array(
)
)
),
'Level 2f' => array(
'Level 3g' => array(
'Level 4h' => array(
)
)
),
),
);
现在我想得到一个索引,如4c级,并让它返回它的父级:
$return = array(
'Level 1c' => array(
'Level 2c' => array(
'Level 3c' => array(
'Level 4c' => array(
)
)
)
)
);
到目前为止,我想到的最好的方法是下面的函数它将以字符串形式返回,有点像。
function getIndexesParents($needle,$haystack,$parentKey=false,$debug=''){
foreach($haystack as $index => $child){
echo '@'.$index.' parentKey is "'.$parentKey.'"<br/>';
if( $parentKey == false ){
$parentKey = $index;
echo 'New parentKey is "'.$parentKey.'"<br/>';
}
else{
$parentKey.= '->'.$index;
}
if( $index == $needle ){
return $parentKey;
}
else if( is_array($child) && count($child) > 0){
echo "Going into next array under parentKey '$parentKey'<br/>";
$result = getIndexesParents($needle,$child,$parentKey,'recursion');
if( $result == false ){
$parentKey = false;
}
else{
return $result;
}
}
else{
return false;
}
}
}
这将返回"1c级-> 2c级-> 3c级-> 4c级"我正在构建这个解决方案,但坦率地说,代码是丑陋的,难以阅读。有人能解出来吗?
这基本上使用相同的逻辑来生成字符串,但我认为它更紧凑。我想,这篇文章是否难看,是否难读,是见仁见智的事。
function get_path($array, $target, $path = "") {
if (is_array($array)) {
foreach ($array as $key => $value) {
if ($key == $target) {
return $path ? "$path->$key" : $key;
}
$branch = get_path($value, $target, $path ? "$path->$key" : $key);
if ($branch) {
return $branch;
}
}
}
};
当我最初回答这个问题时,我误解了它;我以为你只是想用一种更短的方式来得到路径的字符串表示。这个函数应该返回实际的数组路径(如果没有找到目标键,则返回null
)。
function get_path($subject, $target) {
if (is_array($subject)) {
if (isset($subject[$target])) return $subject;
else {
foreach ($subject as $key => $value) {
$result = get_path($value, $target);
if ($result) return [$key => $result];
}
}
}
}