PHP数组:当数组的结构未知时修改一个值

PHP数组:当数组的结构未知时修改一个值,php,arrays,multidimensional-array,Php,Arrays,Multidimensional Array,问题 如果事先不知道数组的结构,如何修改PHP数组中的值 示例 在下面的数组中,我必须在数组中的'system'='knoppix'部分将'fave_color'更改为'blue'。。。问题是我不知道运行时数组的结构是什么,因此我不能简单地执行以下操作: $myarray['settings']['user_prefs']['otherhost']['fave_color'] = 'blue'; 这将不起作用,因为在运行时fave_颜色的嵌套是未知的 此外,我感兴趣的fave_颜色键取决于系统

问题

如果事先不知道数组的结构,如何修改PHP数组中的值

示例

在下面的数组中,我必须在数组中的'system'='knoppix'部分将'fave_color'更改为'blue'。。。问题是我不知道运行时数组的结构是什么,因此我不能简单地执行以下操作:

$myarray['settings']['user_prefs']['otherhost']['fave_color'] = 'blue';
这将不起作用,因为在运行时fave_颜色的嵌套是未知的

此外,我感兴趣的fave_颜色键取决于系统数组键

我必须找到值为“knoppix”的,然后更改相应的“fave_color”值,确保不更改数组中的任何其他fave_color值

'settings' => array(
  'user_prefs'=>array(
    'localhost'=>array(
      'fave_color'=>'orange',
      'system'    =>'unbuntu',
    ),
    'otherhost'=>array(
      'fave_color'=>'yellow',
      'system'    =>'knoppix',
    ),        
  ),
),
您可以使用并检查键是否等于“knoppix”

function findKnoppix(&$value, $key)
{
    if($value == 'knoppix') $value = 'NEW VALUE';
}

array_walk_recursive($myArray, 'findKnoppix');
您可以使用并检查键是否等于“knoppix”

function findKnoppix(&$value, $key)
{
    if($value == 'knoppix') $value = 'NEW VALUE';
}

array_walk_recursive($myArray, 'findKnoppix');

我知道这个问题已经问了几个月了,但是我遇到了同样的问题,我想出了一个我非常喜欢的解决方案,并且我认为有人曾经问过这个问题。首先,有几个想法:

1) 即使必须来回转换,也可以使用XPath或本机PHP数组以外的任何东西吗?当然,要衡量性能的影响,但请尝试一下——使用中描述的查询样式可能会让您头痛,而不会产生巨大的开销

2) 你能改变阵列的结构吗?如果
system
是一个重要的键,那么有没有充分的理由将其嵌套在该深度?如果将数组重新构造为“按系统类型设置”,则该数组可能不够紧凑,但遍历起来可能会容易得多

最后,这是我解决问题的方法,我想你可以适应你的方法。如果需要添加更复杂的逻辑,例如检查必要的同级,我将为回调函数添加可选的第三个参数

/**
 * Sets key/value pairs at any depth on an array.
 * @param $attrs an array of key/value pairs to be set/added
 * @param $data the array you want to affect
 */
function setAttributes($attrs, &$data)
{
    foreach ($attrs as $name => $value) {
        if (strpos($name, '.') === false) {
            // If the array doesn't contain a special separator character,
            // just set the key/value pair. If $value is an array,
            // you will set nested key/value pairs just fine.
            $data[$name] = $value;
        } else {
            // In this case we're trying to target a specific nested key
            // without overwriting any other siblings/ancestors. The period
            // is my separator character -- you can change it to any unique
            // string that is invalid for a key in your system.
            $keys = explode('.', $name);
            // Set the root of the tree.
            $opt_tree =& $data;
            // Start traversing the tree using the specified keys.
            while ($key = array_shift($keys)) {
                // If there are more keys after the current one...
                if ($keys) {
                    if (!isset($opt_tree[$key]) || !is_array($opt_tree[$key])) {
                        // Create this node if it doesn't already exist.
                        $opt_tree[$key] = array();
                    }
                    // Here's the fun bit -- redefine the "root" of the tree
                    // (assignment by reference) then process the next key.
                    $opt_tree =& $opt_tree[$key];
                } else {
                    // This is the last key to check, so assign the value.
                    $opt_tree[$key] = $value;
                }
            }
        }
    }
}
示例用法:

$x = array();
setAttributes(array('foo' => 'bar', 'baz' => array('quux', 42)), $x);
print_r($x); // $x has the same structure as the first argument
setAttributes(array('jif.snee' => 'hello world'), $x);
print_r($x); // $x now has a jif key whose value is snee => hello world
    // if jif.snee already existed, this call would have overwritten
    // that value without modifying any other values

我知道这个问题已经问了几个月了,但是我遇到了同样的问题,我想出了一个我非常喜欢的解决方案,并且我认为有人曾经问过这个问题。首先,有几个想法:

1) 即使必须来回转换,也可以使用XPath或本机PHP数组以外的任何东西吗?当然,要衡量性能的影响,但请尝试一下——使用中描述的查询样式可能会让您头痛,而不会产生巨大的开销

2) 你能改变阵列的结构吗?如果
system
是一个重要的键,那么有没有充分的理由将其嵌套在该深度?如果将数组重新构造为“按系统类型设置”,则该数组可能不够紧凑,但遍历起来可能会容易得多

最后,这是我解决问题的方法,我想你可以适应你的方法。如果需要添加更复杂的逻辑,例如检查必要的同级,我将为回调函数添加可选的第三个参数

/**
 * Sets key/value pairs at any depth on an array.
 * @param $attrs an array of key/value pairs to be set/added
 * @param $data the array you want to affect
 */
function setAttributes($attrs, &$data)
{
    foreach ($attrs as $name => $value) {
        if (strpos($name, '.') === false) {
            // If the array doesn't contain a special separator character,
            // just set the key/value pair. If $value is an array,
            // you will set nested key/value pairs just fine.
            $data[$name] = $value;
        } else {
            // In this case we're trying to target a specific nested key
            // without overwriting any other siblings/ancestors. The period
            // is my separator character -- you can change it to any unique
            // string that is invalid for a key in your system.
            $keys = explode('.', $name);
            // Set the root of the tree.
            $opt_tree =& $data;
            // Start traversing the tree using the specified keys.
            while ($key = array_shift($keys)) {
                // If there are more keys after the current one...
                if ($keys) {
                    if (!isset($opt_tree[$key]) || !is_array($opt_tree[$key])) {
                        // Create this node if it doesn't already exist.
                        $opt_tree[$key] = array();
                    }
                    // Here's the fun bit -- redefine the "root" of the tree
                    // (assignment by reference) then process the next key.
                    $opt_tree =& $opt_tree[$key];
                } else {
                    // This is the last key to check, so assign the value.
                    $opt_tree[$key] = $value;
                }
            }
        }
    }
}
示例用法:

$x = array();
setAttributes(array('foo' => 'bar', 'baz' => array('quux', 42)), $x);
print_r($x); // $x has the same structure as the first argument
setAttributes(array('jif.snee' => 'hello world'), $x);
print_r($x); // $x now has a jif key whose value is snee => hello world
    // if jif.snee already existed, this call would have overwritten
    // that value without modifying any other values

你不知道数组的结构是什么意思?是随机的吗?它一定有某种结构,否则你不知道你想改变什么值。我知道有一个键“system”,我知道有一个对应的兄弟键“fave_color”。。。我不知道这些钥匙在数组中的位置。。。(我不知道是在设置下,还是在设置/用户首选项或设置/其他主机下)当需要将fave_颜色从“黄色”更改为“蓝色”时。。此外,我不能只更改fave_颜色,但我必须在system='knoppix'的分支中更改特定的fave_颜色。cakephp::set是另一个选项,请参见“展平”方法。你不知道数组的结构是什么意思?是随机的吗?它一定有某种结构,否则你不知道你想改变什么值。我知道有一个键“system”,我知道有一个对应的兄弟键“fave_color”。。。我不知道这些钥匙在数组中的位置。。。(我不知道是在设置下,还是在设置/用户首选项或设置/其他主机下)当需要将fave_颜色从“黄色”更改为“蓝色”时。。此外,我不能只更改fave_颜色,但我必须在system='knoppix'的分支中更改特定的fave_颜色。cakephp::set是另一个选项,请参见“展平”方法。是的,但是我如何修改对应的fave_颜色键下的值是的,但是如何修改对应的fave_颜色键下的值