2011-02-25 42 views
0

问题PHP数组:修改值当阵列的结构是未知

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

在下文阵列,我在阵列,其中“系统” ==“的knoppix”的一部分以改变“fave_color”到“蓝色” ...问题是我不知道数组的结构将在运行什么,所以我不能简单地做

$myarray['settings']['user_prefs']['otherhost']['fave_color'] = 'blue'; 

这是行不通的,因为嵌套在运行时的fave_color未知

此外,我感兴趣的fave_color密钥是,具体取决于系统阵列密钥

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

'settings' => array(
    'user_prefs'=>array(
    'localhost'=>array(
     'fave_color'=>'orange', 
     'system' =>'unbuntu', 
    ), 
    'otherhost'=>array(
     'fave_color'=>'yellow', 
     'system' =>'knoppix', 
    ),   
), 
), 
+0

你是什么意思你不知道数组的结构?它是随机的吗?必须有一些结构,或者你不知道你想要改变什么样的价值。 – meagar 2011-02-25 21:52:37

+0

我知道有一个关键的'系统',我知道有一个相应的兄弟关键'fave_color'...我不知道这些关键将位于数组中的位置......(我不知道是否它会在设置或设置/ user_prefs或设置/ otherhost),当它需要将fave_color从'黄色'更改为'蓝色'。此外,我不能只改变fave_color,但我必须更改*特定* fave_color在system =='knoppix'的分支中。 – dreftymac 2011-02-25 21:56:49

+0

cakephp :: set是另一个选项,请参阅“flatten”方法。 – dreftymac 2011-10-31 14:22:23

回答

2

您可以使用array_walk_recursive并检查密钥是否等于'knoppix'。

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

array_walk_recursive($myArray, 'findKnoppix'); 
+0

是的,但后来我怎么修改对应的fave_color键下的值 – dreftymac 2011-02-25 22:03:27

+0

值是通过引用传递的,我已经更新了我的例子。 – Nazariy 2011-02-25 22:10:35

1

我知道这个问题是一对夫妇个月大,但我遇到了同样的问题,有解决办法,我真的很喜欢过来了,想通有人因此不得不之前问一下吧。首先,有几个想法:

1)即使您必须来回转换,您是否可以使用XPath或本地PHP数组以外的其他任何东西?当然,请衡量性能点击量,但请尝试一下 - 使用your related question中描述的查询方式可能会为您节省头痛,而不会产生巨大的开销。

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