如何实现编写狡猾的数组写入功能?

时间:2011-11-08 19:13:56

标签: php arrays algorithm recursion

修改

我知道我是这里的新海报,但我不是StackOverflow的新手。我从未见过人们为问题制定全新的解决方案,正如我在下面看到的那样。我提供了输入,输出和预期输出。接受的答案将符合这些准则。


我正在尝试编写一个如下所述的数组写入功能

// existing array
$config = array("preserve" => "please");

function set($key, $value){
    global $config;
    if(count($keys = explode(':', $key)) > 1){
        $key = array_shift($keys);
        while($k = array_pop($keys)){
            $value = array($k => $value);
        }
    }
    return $config[$key] = $value;   
}

// set
set("foo", "bar");
set("pokemon:trainer", "ashk");
set("pokemon:favorite", "diglett"); // overwrites pokemon:trainer :(

print_r($config);

输出

Array
(
    [preserve] => please
    [foo] => bar
    [pokemon] => Array
        (
            [favorite] => diglett
        )

)

哦不!谁是口袋妖怪训练师? Ash Ketchum已被遗忘!


我理解为什么它会破裂,但我无法找到我应该如何编写这个功能。我觉得需要递归,但我不确定如何实现它:\

输出

Array
(
    [preserve] => please
    [foo] => bar
    [pokemon] => Array
        (
            [trainer] => ashk
            [favorite] => diglett
        )

)

5 个答案:

答案 0 :(得分:3)

似乎更容易使用对象。

$config = new stdClass();
$config->preserve = 'please';
$config->foo = 'bar';

$config->pokemon = new stdClass();
$config->pokemon->trainer= 'ashk';
$config->pokemon->favorite = 'diglette';

var_dump($config);

或者更好的是,创建一个自定义类,其行为与方法和受保护数据完全相同。

编辑:

也许是这样的。你当然可以让它表现得像你喜欢的那样。

class config {
   protected $preserve;
   protected $data = array();
   protected $pokemonData = array();

   public function __construct($preserve) {
      $this->preserve = $preserve;
   }

   public function set($key, $value) {
      $this->data[$key] = $value;
   }

   public function setPokemon($key, $value) {
      $this->pokemonData[$key] = $value;
   }

   public function get($key) {
      if (isset($this->data[$key]) === true) {
         return $this->data[$key];
      } else {
         return false;
      }
   }

   public function getPokemon($key) {
      if (isset($this->pokemonData[$key]) === true) {
         return $this->pokemonData[$key];
      } else {
         return false;
      }
   }

   public function getAsArray() {
      $output = array(
         'preserve' => $this->preserve,
         'pokemon' => $this->pokmonData
      );
      return $output + $this->data;
   }
}

答案 1 :(得分:1)

$config = array('preserve' => 'please');

function set($config, $key, $value) {
    $keys = explode(':', $key);
    $left_key = array_shift($keys);
    if (count($keys) === 0) {
        $config[$left_key] = $value;
    } else {
        if (isset($config[$left_key]) === false) $config[$left_key] = array();
        $config[$left_key] = set($config[$left_key], implode(':', $keys), $value);
    }
    return $config;
}

用法:

$config = set($config, $key, $value);

使用引用操作符进行编辑:

// change to this
function set(&$config, $key, $value) {

// also this line
$config[$left_key] = set($config[$left_key], implode(':', $keys), $value);
// would then need to be this instead
set($config[$left_key], implode(':', $keys), $value);

新用法:

set($config, $key, $value);

答案 2 :(得分:0)

执行set("pokemon:???", "someVal");时,您正在写pokemon内的上一组$config数组。也许您可以在key

中添加某种计数器/ ID
function set($key, $value){
    global $config;
    if(count($keys = explode(':', $key)) > 1){
        $key = array_shift($keys);
        while($k = array_pop($keys)){
            $value = array($k => $value);
        }
        $config[$key][] = $value;
        return;
    }
    $config[$key] = $value;   
}

答案 3 :(得分:0)

$config = array("preserve" => "please");

function set($key, $value){
    global $config;
    if(strpos($key,':')==true) { 
        $config[substr($key,0,strpos($key,':'))][substr($key,strpos($key,':')+1)] = $value;
    }
    else {
        $config[$key] = $value;
    }
}
set("foo", "bar");
set("pokemon:trainer", "ashk");
set("pokemon:favorite", "diglett"); // overwrites pokemon:trainer :(

print_r($config);

只要您只有一个:在您的输入中,这是有效的。

答案 4 :(得分:0)

现在我有100多名代表,我终于可以将其作为真实答案发布,并将其标记为已接受。

这是一个非常简洁的小片段:)

// existing array
$config = array("preserve" => "please");

function set($key, $value){
    global $config;
    if(count($keys = explode(':', $key)) > 1){
        $key = array_shift($keys);
        while($k = array_pop($keys)){
            $value = array($k => $value);
        }
        // *** fixed here ***
        // merge new data with possible existing data
        if(array_key_exists($key, $config)){
            $value = array_merge_recursive($config[$key], $value);
        }
    }
    return $config[$key] = $value;   
}

// set
set("foo", "bar");
set("pokemon:trainer", "ashk");
set("pokemon:favorite", "diglett"); // no longer overwrites pokemon:trainer :)

print_r($config);