在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
)
答案 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;
}
}