如何使用字符串作为数组索引路径来检索值?

10

假设我有一个数组如下:

Array
(
    [0] => Array
        (
            [Data] => Array
                (
                    [id] => 1
                    [title] => Manager
                    [name] => John Smith
                )
         )
    [1] => Array
        (
            [Data] => Array
                 (
                     [id] => 1
                     [title] => Clerk
                     [name] =>
                         (
                             [first] => Jane
                             [last] => Smith
                         )
                 )

        )

)

我希望能够编写一个函数,可以将一个字符串作为数组索引路径传递给它,并返回相应的数组值,而不使用eval()。这是否有可能?

function($indexPath, $arrayToAccess)
{
    // $indexPath would be something like [0]['Data']['name'] which would return 
    // "Manager" or it could be [1]['Data']['name']['first'] which would return 
    // "Jane" but the amount of array indexes that will be in the index path can 
    // change, so there might be 3 like the first example, or 4 like the second.

    return $arrayToAccess[$indexPath] // <- obviously won't work
}
10个回答

17

稍晚了一点,但是希望能帮助到某些人:

// $pathStr = "an:string:with:many:keys:as:path";
$paths = explode(":", $pathStr); 
$itens = $myArray;
foreach($paths as $ndx){
    $itens = $itens[$ndx];
}

现在,itens是你想要的数组的一部分。

[]里面的

Labs


11

您可以将路径作为数组(从左到右)使用,然后使用递归函数:

$indexes = {0, 'Data', 'name'};

function get_value($indexes, $arrayToAccess)
{
   if(count($indexes) > 1) 
    return get_value(array_slice($indexes, 1), $arrayToAccess[$indexes[0]]);
   else
    return $arrayToAccess[$indexes[0]];
}

好的。提示给复制粘贴者:'getValue' 的递归调用与函数名 'get_value' 不完全匹配。它们应该匹配才能正常工作。 - grossvogel

3
尝试以下代码,其中 $indexPath 的格式类似于文件路径,即:
'<array_key1>/<array_key2>/<array_key3>/...'.

function($indexPath, $arrayToAccess)
{
    $explodedPath = explode('/', $indexPath);
    $value =& $arrayToAccess;
    foreach ($explodedPath as $key) {
        $value =& $value[$key];
    }
    return $value;
}

例如,使用问题中的数据,“$indexPath = '1/Data/name/first'”将返回“$value = Jane”。

3

这是一个老问题,但由于经常出现,因此被引用了。

有递归函数,但我使用参考:

function array_nested_value($array, $path) {
    $temp = &$array;

    foreach($path as $key) {
        $temp =& $temp[$key];
    }
    return $temp;
}

$path  = array(0, 'Data', 'Name');
$value = array_nested_value($array, $path);

1
function($indexPath, $arrayToAccess)
{
    eval('$return=$arrayToAccess'.$indexPath.';');
    return $return;
}

0
除了AbraCadaver之外:
function array_nested_value($array, $path) {

    foreach($path as $key) {

        $array = $array[$key];
    }

    return $array;
}

$path  = array(0, 'Data', 'Name');
$value = array_nested_value($array, $path);

可能的用途

function get_array_value($array=array(), $path=array()){

    foreach($path as $key) {

        if(isset($array[$key])){

            $array=$array[$key];
        }
        else{

            $array=NULL;
            break;
        }
    }

    return $array;
}

function custom_isset($array=array(), $path=array()){

    $isset=true;

    if(is_array($array)&&is_null(get_array_value($array, $path))){

        $isset=false;
    }

    return $isset;
}

function is($array=array(), $path=array()){

    $is=false;

    if(is_array($array)){

        $array_value=get_array_value($array, $path);

        if(is_bool($array_value)){

            $is=$array_value;
        }
    }

    return $is;
}

例子

    $status=[];

    $status['updated']=true;

        if(is($status,array('updated'))){

                //do something...

        }

资源

https://gist.github.com/rafasashi/0d3ebadf08b8c2976a9d


0

如果您想使用字符串解析的方式,这里有一种完成任务的方法。

$data[0]["Data"]["stuff"] = "cake";

$path = "[0][\"Data\"]['stuff']";

function indexPath($path,$array){
    preg_match_all("/\[['\"]*([a-z0-9_-]+)['\"]*\]/i",$path,$matches);

    if(count($matches[1]) > 0) {
        foreach ($matches[1] as $key) {
                if (isset($array[$key])) {
                        $array = $array[$key];
                } else {
                        return false;
                }
        }
    } else {
        return false;
    }

return $array;
}

print_r(indexPath($path,$data));

0

你需要解析indexPath字符串。选择一些分隔符(例如“.”),读取文本直到“.”,那将是第一个键,然后读取剩余部分直到下一个“.”,那将是下一个键。重复此过程,直到没有更多的点。

你可以将键存储在数组中。使用foreach循环遍历该数组以获取所需元素。


0

使用 preg_match_all 函数,循环匹配结果可以接近你想要的结果。但是需要小心所有列出的策略,以避免信息丢失。例如,你必须设计一些方法来确保 55 保持 int 类型而不被解析为 string 类型。


-1
如果您已经知道要提取的确切数组元素,为什么还要编写一个函数来执行此操作?直接使用该元素有何问题?
$array[0]['data']['title']

我遇到了相同的问题。我有一个复杂的数组。我需要找到特定的键,获取它的地址,然后获取其他数据,并将其插入到该键中。因此,我基本上需要存储索引的地址,通过它来寻找项目的地址。 - Alexei Rayu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接