【问题标题】:Dynamically accessing multidimensional array value动态访问多维数组值
【发布时间】:2016-07-19 23:30:46
【问题描述】:

我正在尝试查找(或创建)一个函数。我有一个多维数组:

$data_arr = [
    "a" => [
        "aa" => "abfoo",
        "ab" => [
            "aba" => "abafoo",
            "abb" => "abbfoo",
            "abc" => "abcfoo"
        ],
        "ac" => "acfoo"
    ],
    "b" => [
        "ba" => "bafoo",
        "bb" => "bbfoo",
        "bc" => "bcfoo"
    ],
    "c" => [
        "ca" => "cafoo",
        "cb" => "cbfoo",
        "cc" => "ccfoo"
    ]
];

我想使用一维数组访问一个值,如下所示:

$data_arr_call = ["a", "ab", "abc"];

someFunction( $data_arr, $data_arr_call ); // should return "abcfoo"

这似乎已经有这种类型的功能,我只是不知道要搜索什么。

【问题讨论】:

  • 你的意思是访问$data_arr['a']['ab']['abc']
  • 对...它几乎需要['a', 'ab', 'abc'] 并认识到它的意思是$data_arr['a']['ab']['abc']

标签: php function multidimensional-array


【解决方案1】:

试试这个

function flatCall($data_arr, $data_arr_call){
    $current = $data_arr;
    foreach($data_arr_call as $key){
        $current = $current[$key];
    }

    return $current;
}

OP的解释:

$current 变量被迭代构建,如下所示:

flatCall($data_arr, ['a','ab','abc']);

1st iteration: $current = $data_arr['a'];
2nd iteration: $current = $data_arr['a']['ab'];
3rd iteration: $current = $data_arr['a']['ab']['abc'];

您还可以在每次迭代中执行if ( isset($current) ) ... 以提供错误检查。

【讨论】:

  • 缺少$key,它在哪里拉它?哦,我想你的意思是$data_arr_call as $key
  • @philtune 是的,完全正确
  • 虽然这段代码 sn-p 可以解决问题,但including an explanation 确实有助于提高帖子的质量。请记住,您正在为将来的读者回答问题,而这些人可能不知道您的代码建议的原因。也请尽量不要用解释性的 cmets 挤满你的代码,这会降低代码和解释的可读性!
  • 是的,我知道为什么会这样,但就像@Rizier123 所说,你应该写一个解释,我会接受这个答案。谢谢。
  • @Rizier123 我确信这 3 行简单的代码不需要任何解释。如果你不同意,你可以自己做。
【解决方案2】:

你可以使用这个函数来避免整个数组的复制(使用引用),能够返回一个 NULL 值(使用array_key_exists而不是isset),并且当路径没有时抛出异常'存在:

function getItem(&$array, $path) {
    $target = &$array;
    foreach($path as $key) {
        if (array_key_exists($key, $target))
            $target = &$target[$key];
        else throw new Exception('Undefined path: ["' . implode('","', $path) . '"]');
    }
    return $target;
}

演示:

$data = [
    "a" => [
        "aa" => "abfoo",
        "ab" => [
            "aba" => "abafoo",
            "abb" => NULL,
            "abc" => false
        ]
    ]
];

var_dump(getItem($data, ['a', 'ab', 'aba']));
# string(6) "abafoo"
var_dump(getItem($data, ['a', 'ab', 'abb']));
# NULL
var_dump(getItem($data, ['a', 'ab', 'abc']));
# bool(false)
try {
    getItem($data, ['a', 'ab', 'abe']);
} catch(Exception $e) {
    echo $e->getMessage();
}
# Undefined path: ["a","ab","abe"]

注意这个功能可以改进,比如可以测试参数是不是数组。

【讨论】:

    【解决方案3】:

    想发布一个更优雅的解决方案:array_reduce

        $data_arr = [
            "a" => [
                ...
                "ab" => [
                    ...
                    "abc" => "abcfoo"
                ],
                ...
            ],
            ...
        ];
    
        $result = array_reduce(["a", "ab", "abc"], function($a, $b) {
            return $a[$b];
        }, $data_arr);
    
        // returns "abcfoo"
    

    我最近一直在使用 Javascript 的 Array.reduce() 将一些遗留代码更新为 ES6:

    JS:
    const data_obj = {...};
    let result = ['a','ab','abc'].reduce((a, b) => a[b], data_obj);
    

    【讨论】:

      【解决方案4】:

      你需要这样的函数:

      function getValue($data_arr, $data_arr_call) {
          foreach ($data_arr_call as $index) {
              if (isset($data_arr[$index])) {
                  $data_arr = $data_arr[$index];
              } else {
                  return false;
              }
          }
          return $data_arr;
      }
      

      并像这样使用它:

      $data_arr = [
          "a" => [
              "ab" => [
                  "abc" => "abbfoo",
              ],
          ],
      ];
      $data_arr_call = ["a", "ab", "abc"];
      $value = getValue($data_arr, $data_arr_call);
      if ($value) {
          // do your stuff
      }
      

      【讨论】:

        猜你喜欢
        • 2014-10-15
        • 1970-01-01
        • 1970-01-01
        • 2013-06-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-09-01
        相关资源
        最近更新 更多