用于在PHP中使用一个特定键从数组中提取值的泛型函数

时间:2010-06-15 10:46:37

标签: php arrays multidimensional-array

在PHP中是否可以从具有特定键路径的数组中提取值并返回这些值的数组?我将用一个例子来解释:

$user =
  array (
    array(
      'id' => 1,
      'email' =>'asd@example.com',
      'project' => array ('project_id' => 222, 'project_name' => 'design')
    ),
    array(
      'id' => 2,
      'email' =>'asd2@example.com',
      'project' => array ('project_id' => 333, 'project_name' => 'design')
    )
  );

/** I have to write a function something like: */
$projectIds = extractValuesWithKey($user, array('project', 'project_id'));
print_r($projectIds);

输出:

Array(
[0] => 222,
[1] => 333
)

4 个答案:

答案 0 :(得分:2)

通过使用递归迭代器来展平数组,我会采用不同的方法(并不是基于数组函数的答案有任何错误)使关键路径比较相当简单。

function extractValuesWithKey($array, $keys) {
    $iterator   = new RecursiveIteratorIterator(new RecursiveArrayIterator($array));
    $keys_count = count($keys);
    // No point going deeper than we have to!
    $iterator->setMaxDepth($keys_count);

    $result = array();
    foreach ($iterator as $value) {
        // Skip any level that can never match our keys
        if ($iterator->getDepth() !== $keys_count) {
            continue;
        }
        // Build key path to current item for comparison
        $key_path = array();
        for ($depth = 1; $depth <= $keys_count; $depth++) {
            $key_path[] = $iterator->getSubIterator($depth)->key();
        }
        // If key paths match, add to results
        if ($key_path === $keys) {
            $result[] = $value;
        }
    }
    return $result;
}

为了使整个事情更有用,您甚至可以将代码包装到自定义FilterIterator而不是基本功能中,但我想这可能完全是一个不同的问题。

答案 1 :(得分:1)

嗯,这比你想象的容易。

function extractValuesWithKey($array, $parts) {
    $return = array();
    $rawParts = $parts;
    foreach ($array as $value) {
        $tmp = $value;
        $found = true;
        foreach ($parts as $key) {
            if (!is_array($tmp) || !isset($tmp[$key])) {
                $found = false;
                continue;
            } else {
                $tmp = $tmp[$key];
            }
        }
        if ($found) {
            $return[] = $tmp;
        }
    }
    return $return;
}

答案 2 :(得分:1)

如果“关键路径”不是动态的,您可以使用array_map执行单行操作:

$projectIds = array_map(function($arr) { return $arr['project']['project_id']; }, $user);

或者,对于动态路径:

function extractValuesWithKey($users, $path) {
 return array_map(function($array) use ($path) {
  array_walk($path, function($key) use (&$array) { $array = $array[$key]; });
  return $array;
 }, $users);
}

闭包/匿名函数仅适用于PHP 5.3+,我不知道这将如何比较性能与双foreach循环。另请注意,没有错误检查以确保路径存在。

答案 3 :(得分:0)

我在我的一个项目中也使用了类似的功能,也许你觉得这很有用:

    function extractValuesWithKey($data, $path) {
        if(!count($path)) return false;

        $currentPathKey = $path[0];

        if(isset($data[$currentPathKey])) {
            $value = $data[$currentPathKey];
            return is_array($value) ? extractValuesWithKey($value, array_slice($path, 1)) : $value;
        }
        else {
            $tmp = array();

            foreach($data as $key => $value) {
                if(is_array($value)) $tmp[] = extractValuesWithKey($value, $path);
            }

            return $tmp;
        }
    }