【问题标题】:Is it possible for a variable to evaluate to a multi-dimensional PHP array index变量是否可以评估为多维 PHP 数组索引
【发布时间】:2013-04-25 18:47:24
【问题描述】:

给定一个多维数组或字典$array

假设$array['foo']['bar']['baz'] = 'something';

除了通过 eval 语句对我来说,还有其他方法可以使用多维索引foo/bar/baz吗? (用例是动态创建索引,即函数不知道 /foo/bar/baz/ 是什么)。

我能想到的唯一方法是:

$item = testGetIndex($array, "'foo']['bar']['baz'");

function testGetIndex($array, $index) {
  eval('$item = $array[' . $index . '];');
  return $item;
}

注意: 我应该提到我不想搜索这个数组。这是一个奇怪的用例。我被传递了一个非常大的多维数组,而不得不使用像这样的构造是很难看的。

$array[foo][bar]..[baz] 对数组进行修改。

【问题讨论】:

  • 不确定我是否完全理解你的问题,但听起来你正在寻找类似array_search:php.net/manual/en/function.array-search.php的数组搜索
  • eval 将脚本与编译语言区分开来,非常适合这种情况;只要您知道自己在做什么(没有未经审查的输入)。手动遍历方法同样有效,但是当您说“进行修改”时,您将需要一种基于引用的遍历方法。
  • @mario 是的,我确实喜欢我简单易懂的 eval 策略,但我被警告不要将 eval 用于任何事情。我希望 PHP 有一个数组函数来为我做这件事:(

标签: php arrays


【解决方案1】:

明目张胆地重用my answer here

function recurseKeys(array $keys,array $array){
    $key = array_shift($keys);
    if(!isset($array[$key])) return null;
    return empty($keys) ?
        $array[$key]:
        recurseKeys($keys,$array[$key];
}
$values = recurseKeys(explode('/','foo/bar/baz'),$yourArray);

编辑: 正如 Jack 指出的,不需要递归:

function findByKey(array $keys,array $array){
    while(!is_null($key = array_shift($keys))){
        if(!isset($array[$key])) return null;
        $array = $array[$key];
    }
    return $array;
}
$values = findByKey(explode('/','foo/bar/baz'),$yourArray);

【讨论】:

  • 为什么要递归?这个问题可以很容易地迭代表达。
  • 原来我们都错了,因为 OP 想要一种方法来修改数组而不是找到值。
  • @jack: 很好地参考了救援...做了你刚刚发布的确切改动,所以我不会打扰;)
【解决方案2】:

使用路径修改数组:

function setPath(&$root, $path, $value)
{
        $paths = explode('/', $path);
        $current = &$root;

        foreach ($paths as $path) {
                if (isset($current[$path])) {
                        $current = &$current[$path];
                } else {
                        return null;
                }
        }

        return $current = $value;
}
$path = 'foo/bar/baz';
$root = array('foo' => array('bar' => array('baz' => 'something')));

setPath($root, $path, '123');

您可以调整函数以仅返回对您要更改的元素的引用:

function &getPath(&$root, $path)
{
        $paths = explode('/', $path);
        $current = &$root;

        foreach ($paths as $path) {
                if (isset($current[$path])) {
                        $current = &$current[$path];
                } else {
                        return null;
                }
        }

        return $current;
}

$x = &getPath($root, $path);

$x = 456; // $root['foo']['bar']['baz'] == 456

【讨论】:

    【解决方案3】:

    一个简单的循环就可以做到,比如:

    function get(array $array, $keys) {
      $val = $array;
      foreach (explode('/', $keys) as $part) {
        if (!isset($val[$part])) {
          return null;
        }
        $val = $val[$part];
      }
      return $val;
    }
    
    $array['foo']['bar']['baz'] = 'something';
    echo get($array, 'foo/bar/baz');
    

    http://ideone.com/vcRvXW

    编辑

    如需修改,请使用引用:

    function set(array &$array, $keys, $value) {
      $val = &$array;
      foreach (explode('/', $keys) as $part) {
        if (!isset($val[$part])) {
          $val[$part] = array();
        }
        $val = &$val[$part];
      }
      $val = $value;
    }
    

    http://ideone.com/WUNhF6

    【讨论】:

    • 显然,OP 需要函数来修改数组,而不仅仅是读取它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-09
    • 1970-01-01
    • 1970-01-01
    • 2015-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多