3

我正在尝试访问一个嵌套数组(一个包含数组的数组,其中包含数组......)

给定数组和键的路径,我需要获取最后一个值。

给定 foo 和 a...zi 需要得到

foo[a][b][c]…[x][y][z]

我想知道是否有比这更优雅的方式?

function getValueRecursive(array $array, string ...$identifyer){
    $value = $array;
    
    foreach($identifyer as $key){
        if(!key_exists($key, $value))
            return NULL;
        
        $value = $value[$key];
    }
    
    return $value;
}

$foo = [
    'a' => [
        'b' => [
            'c' => "Hallo Welt!"
        ]
    ]
];

echo getValueRecursive($foo, 'a', 'b', 'c');                                    // Returns "Hallo Welt!"
4

3 回答 3

3

PHP 代码演示

<?php

$foo = [
    'a' => [
        'b' => [
            'c' => "Hallo Welt!"
        ]
    ]
];
$result=array();
array_walk_recursive($foo, function($value,$key) use (&$result){
    $result[]=$value;
});
print_r($result[0]);

或者

<?php
ini_set("display_errors", 1);
$foo = [
    'a' => [
        'b' => [
            'c' => "Hallo Welt!"
        ]
    ]
];
echo getValueOfArray($foo,"a","b","c");
function getValueOfArray($array)
{
    $args=func_get_args();
    unset($args[0]);
    $string="";
    foreach($args as $value)
    {
        $string.="['$value']";
    }
    eval('if(isset($array'.$string.'))
    {
        $result= $array'.$string.';
    }');
    return $result;
}

输出: Hallo Welt!

于 2017-04-11T11:41:29.153 回答
1

前段时间我写了数组库,使用ArrayAccess接口来实现这样的操作。它不仅允许检索,还允许存储和删除值。

对于所有offset*()方法,我使用了高阶方法walkThroughOffsets

protected function walkThroughOffsets(
        &$array,
        Callable $baseCaseAction,
        Callable $offsetNotExistsAction
    ) {
        $offset = array_shift($this->offsets);
        if (is_scalar($offset) && isset($array[$offset])) {
            if (empty($this->offsets)) {
                return $baseCaseAction($array, $offset);
            }
            return $this->walkThroughOffsets(
                $array[$offset],
                $baseCaseAction,
                $offsetNotExistsAction
            );
        }
        return $offsetNotExistsAction($array, $offset);
    }

有了这个方法,您可以offsetGet像这样实现方法(当您尝试访问数组值时调用):

public function offsetGet($offset)
    {
        $this->setOffsets($offset);
        return $this->walkThroughOffsets(
            $this->container,
            function ($array, $offset) {
                return $array[$offset];
            },
            $this->undefinedOffsetAction
        );
    }

然后,您可以像使用通常的数组一样简单地获取值:

$array = new CompositeKeyArray([
    'foo' => [
        'bar' => 'baz'
    ]
]);

var_dump($array[['foo', 'bar']]); // => string(3) "baz"
var_dump($array[['foo', 'quux']]); // => PHP Fatal error:  Uncaught UndefinedOffsetException: Undefined offset quux.
于 2017-04-11T12:21:03.863 回答
0

您的方法与我推荐的方法非常相似。我想这基本上是一种“堆叠”技术,而不是对自定义函数进行条件/重复调用。我确实发现您的方法足够优雅。

调整:

  • 不要将传入的可变参数转换为字符串数组——让元素的数据类型保持原样。
  • variadic 变量包含一组表示键的值——因此命名变量。
  • 此自定义函数调用的返回值可能是任何数据类型(包括null),因此return null在提供无效键路径时随意使用是不合适的。而是抛出一个异常,以便在调用函数的任何地方都可以区分结果。

代码:(演示)(边缘案例

function getValueRecursive(array $array, ...$keys) {
    foreach ($keys as $key) {
        if (!key_exists($key, $array)) {
            throw new Exception('key path invalid');
        }
        $array = $array[$key];
    }
    return $array;
}

$foo = [
    'a' => [
        'b' => [
            'c' => "Hallo Welt!"
        ]
    ]
];

try {
    var_export(getValueRecursive($foo, 'a', 'b', 'c'));
    echo "\n---\n";
    var_export(getValueRecursive($foo, 'a', 'b'));
    echo "\n---\n";
    var_export(getValueRecursive($foo, 0, 'b', 'c'));
} catch (Exception $e) {
    echo 'Caught exception: ' .  $e->getMessage();
}

输出:

'Hallo Welt!'
---
array (
  'c' => 'Hallo Welt!',
)
---
Caught exception: key path invalid
于 2021-06-25T13:53:59.503 回答