循环遍历多维数组并使用父键作为前缀

时间:2016-01-23 23:25:50

标签: php arrays multidimensional-array laravel-5

在Laravel 4或5中使用Eloquent时,$model->with()方法将该方法用作关系名称。因此,如果我们向用户提供他的个人资料,那么将返回:

$user = [
  'id' => 1,
  'name' => 'Example',
  'profile' => [
    'last_login' => '10-10-1900',
    'another_field' => 'with some data',
    'actions' => [
      0 => 'Logged in',
      1 => 'Logged out',
      2 => 'Signed up for news letter'
    ]
  ]
];

我想展平整个数组并使用关系的键作为前缀,即例如:

$user = [
  'id' => 1,
  'name' => 'Example',
  'profile_last_login' => '10-10-1900',
  'profile_another_field' => 'with some data',
  'profile_actions' => [
    0 => 'Logged in',
    1 => 'Logged out',
    2 => 'Signed up for news letter'
  ]
];

我怎样才能做到这一点?

修改

我也想要展平多维数组,如下所示:

$user = [
    'id' => 1,
    'name' => 'Example',
    'profile' => [
        'last_login' => '10-10-1900',
        'another_field' => 'with some data',
        'actions' => [
            0 => 'Logged in',
            1 => 'Logged out',
            2 => 'Signed up for news letter'
        ],
        'friends' => [
            'friend_one' => [
                'name' => 'Test User',
                'email' => 'test@example.com'
            ],
            'friend_two' => [
                'name' => 'Test User',
                'email' => 'test@example.com'
            ]
        ]
    ]
];

进入这个:

$out = [
    'id' => 1,
    'name' => 'Example',
    'profile_last_login' => '10-10-1900',
    'profile_another_field' => 'with some data',
    'profile_actions' => [
        0 => 'Logged in',
        1 => 'Logged out',
        2 => 'Signed up for news letter'
    ],
    'profile_friends_friend_one_name' => 'Test User',
    'profile_friends_friend_one_email' => 'test@example.com',
    'profile_friends_friend_two_name' => 'Test User',
    'profile_friends_friend_two_email' => 'test@example.com'
];

1 个答案:

答案 0 :(得分:0)

原始问题的简单方法(单维)

function flattenParentKey($array, $parentKey)
{
    foreach ($array[$parentKey] as $key => $value)
    {
        $array[$parentKey . '_' . $key] = $value;
    }

    unset($array[$parentKey]);

    return $array;
}

这是PHP Shell中的一个示例(php -a):

php > $user = [
php >   'id' => 1,
php >   'name' => 'Example',
php >   'profile' => [
php >     'last_login' => '10-10-1900',
php >     'another_field' => 'with some data',
php >     'actions' => [
php >       0 => 'Logged in',
php >       1 => 'Logged out',
php >       2 => 'Signed up for news letter'
php >     ]
php >   ]
php > ];
php > $user = flattenParentArray($user, 'profile');
php > var_dump($user);
array(5) {
  ["id"]=>
  int(1)
  ["name"]=>
  string(7) "Example"
  ["profile_last_login"]=>
  string(10) "10-10-1900"
  ["profile_another_field"]=>
  string(14) "with some data"
  ["profile_actions"]=>
  array(3) {
    [0]=>
    string(9) "Logged in"
    [1]=>
    string(10) "Logged out"
    [2]=>
    string(25) "Signed up for news letter"
  }
}
php >

多维数组的递归方法

正如您在评论中提到的那样,我添加到您原来的问题中,这里是我们如何使用嵌套的多维数组执行此操作:

$user = [
    'id' => 1,
    'name' => 'Example',
    'profile' => [
        'last_login' => '10-10-1900',
        'another_field' => 'with some data',
        'actions' => [
            0 => 'Logged in',
            1 => 'Logged out',
            2 => 'Signed up for news letter'
        ],
        'friends' => [
            'friend_one' => [
                'name' => 'Test User',
                'email' => 'test@example.com'
            ],
            'friend_two' => [
                'name' => 'Test User',
                'email' => 'test@example.com'
            ]
        ]
    ]
];

/* Returns true if the specified parameter is an array, is not empty, and is 
 * not a contiguous numeric array).
 */
function isAssociativeArray($array)
{
    if (empty($array) || !is_array($array))
    {
        return false;
    }

    /* Returns true if arrays keys are not numeric or contiguous. */
    return (bool) array_keys($array) !== range(0, count($array) - 1);
}

/* $parentKey will always be null when we first call this function. As
 * it recurses through levels of depth, $parentKey will be passed and
 * appended to.
 */
function flattenChildArrays($array, $parentKey = null)
{
    $outputArray = [];

    foreach ($array as $key => $value)
    {
        /* If we have a $parentKey, our new key will be "$parentKey_$key" */
        $newKey = (($parentKey) ? $parentKey . '_' . $key : $key);

        if (isAssociativeArray($value))
        {
            /* If our $value is an associative array, we'll want to recursively
             * call ourselves again on $value with our new key as the $parentKey.
             */
            $outputArray = array_merge($outputArray, flattenChildArrays($value, $newKey));
        }
        else
        {
            /* If $value is not an associative array (i.e. just a simple value, or a
             * contiguous numeric array, just use the value as it is in our output
             * array. If we have a parent key (because we're inside 1 or more levels
             * of recursion), use "$parentKey_$key" (see where we define $newKey above).
             */
            $outputArray[$newKey] = $value;
        }
    }

    return $outputArray;
}

PHP shell中的一个例子:

php > $user = [
php >     'id' => 1,
php >     'name' => 'Example',
php >     'profile' => [
php >         'last_login' => '10-10-1900',
php >         'another_field' => 'with some data',
php >         'actions' => [
php >             0 => 'Logged in',
php >             1 => 'Logged out',
php >             2 => 'Signed up for news letter'
php >         ],
php >         'friends' => [
php >             'friend_one' => [
php >                 'name' => 'Test User',
php >                 'email' => 'test@example.com'
php >             ],
php >             'friend_two' => [
php >                 'name' => 'Test User',
php >                 'email' => 'test@example.com'
php >             ]
php >         ]
php >     ]
php > ];
php > var_dump(flattenChildArrays($user));
array(11) {
  ["id"]=>
  int(1)
  ["name"]=>
  string(7) "Example"
  ["profile_last_login"]=>
  string(10) "10-10-1900"
  ["profile_another_field"]=>
  string(14) "with some data"
  ["profile_actions_0"]=>
  string(9) "Logged in"
  ["profile_actions_1"]=>
  string(10) "Logged out"
  ["profile_actions_2"]=>
  string(25) "Signed up for news letter"
  ["profile_friends_friend_one_name"]=>
  string(9) "Test User"
  ["profile_friends_friend_one_email"]=>
  string(16) "test@example.com"
  ["profile_friends_friend_two_name"]=>
  string(9) "Test User"
  ["profile_friends_friend_two_email"]=>
  string(16) "test@example.com"
}
php >

递归可能是一个难以理解的主题,因为它需要您通过头脑中的多个级别来跟踪程序,并且很容易忘记您的位置。我建议采用一个简单的例子,并且"单步执行"你的递归函数,逐行,评论每个深度的每个值。

this question的答案提供了有关理解递归的更多信息。