2

我想剖析这样的数组:

[
    "ID",
    "UUID",
    "pushNotifications.sent",
    "campaigns.boundDate",
    "campaigns.endDate",
    "campaigns.pushMessages.sentDate",
    "pushNotifications.tapped"
]

变成这样的格式:

{
    "ID" : 1,
    "UUID" : 1,
    "pushNotifications" : 
        {
            "sent" : 1,
            "tapped" : 1
        },
    "campaigns" :
        {
            "boundDate" : 1,
            "endDate" : 1,
            "pushMessages" :
                {
                    "endDate" : 1
                }  
        }
}

如果我能以类似键路径的方式在关联数组上设置一个值,那就太好了:

//To achieve this:
$dissected['campaigns']['pushMessages']['sentDate'] = 1;

//By something like this:
$keypath = 'campaigns.pushMessages.sentDate';
$dissected{$keypath} = 1;

如何在 PHP 中做到这一点?

4

3 回答 3

4

您可以使用 :

$array = [
        "ID",
        "UUID",
        "pushNotifications.sent",
        "campaigns.boundDate",
        "campaigns.endDate",
        "campaigns.pushMessages.sentDate",
        "pushNotifications.tapped"
];

// Build Data
$data = array();
foreach($array as $v) {
    setValue($data, $v, 1);
}

// Get Value
echo getValue($data, "campaigns.pushMessages.sentDate"); // output 1

使用的功能

function setValue(array &$data, $path, $value) {
    $temp = &$data;
    foreach(explode(".", $path) as $key) {
        $temp = &$temp[$key];
    }
    $temp = $value;
}

function getValue($data, $path) {
    $temp = $data;
    foreach(explode(".", $path) as $ndx) {
        $temp = isset($temp[$ndx]) ? $temp[$ndx] : null;
    }
    return $temp;
}
于 2013-05-05T21:36:29.493 回答
1
function keyset(&$arr, $keypath, $value = NULL)
{
   $keys = explode('.', $keypath);
   $current = &$arr;
   while(count($keys))
   {
      $key = array_shift($keys);
      if(!isset($current[$key]) && count($keys))
      {
         $current[$key] = array();
      }
      if(count($keys))
      {
         $current = &$current[$key];
      }
   }
   $current[$key] = $value;
}

function keyget($arr, $keypath)
{
   $keys = explode('.', $keypath);
   $current = $arr;
   foreach($keys as $key)
   {
      if(!isset($current[$key]))
      {
         return NULL;
      }
      $current = $current[$key];
   }
   return $current;
}

//Testing code:
$r = array();
header('content-type: text/plain; charset-utf8');
keyset($r, 'this.is.path', 39);
echo keyget($r, 'this.is.path');
var_dump($r);

这有点粗糙,我不能保证它的功能是 100%。

编辑:起初你很想尝试使用可变变量,但我过去曾尝试过,但它不起作用,所以你必须使用函数来做到这一点。这适用于一些有限的测试。(我刚刚添加了一个小的编辑来删除不必要的数组分配。)

于 2013-05-05T21:26:11.197 回答
0

与此同时,我想出了(另一个)解决方案:

private function setValueForKeyPath(&$array, $value, $keyPath)
{
    $keys = explode(".", $keyPath, 2);
    $firstKey = $keys[0];
    $remainingKeys = (count($keys) == 2) ? $keys[1] : null;
    $isLeaf = ($remainingKeys == null);

    if ($isLeaf)
        $array[$firstKey] = $value;
    else
        $this->setValueForKeyPath($array[$firstKey], $value, $remainingKeys);
}

对不起,“长”的命名,我来自 Objective-C 世界。:) 所以在每个 keyPath 上调用它,它实际上给了我输出:

fields
Array
(
    [0] => ID
    [1] => UUID
    [2] => pushNotifications.sent
    [3] => campaigns.boundDate
    [4] => campaigns.endDate
    [5] => campaigns.pushMessages.endDate
    [6] => pushNotifications.tapped
)
dissectedFields
Array
(
    [ID] => 1
    [UUID] => 1
    [pushNotifications] => Array
        (
            [sent] => 1
            [tapped] => 1
        )

    [campaigns] => Array
        (
            [boundDate] => 1
            [endDate] => 1
            [pushMessages] => Array
                (
                    [endDate] => 1
                )

        )

)
于 2013-05-05T22:07:28.360 回答