问题
If I have an array which comes from a database like this:
$array = [
'dataset_1' => [
'some' => '...',
'array' => '...',
],
'dataset_2' => [
'some' => '...',
'thing' => '...',
'else' => '...',
]
];
... how can I transform this array to another structure like:
$array = [
'whatever' => [
'some' =>'...',
'array' => '...',
'some' =>'...',
'thing' => '...',
'else' => '...',
]
];
I thought about OptionResolver, but I have no idea so if anyone can give me a hint or an example?
回答1:
You can do it using array_merge along with ..., in case you have an uknown number of datasets, to get your result. Beware though, as you have duplicate keys in your arrays which means that you will lose all duplicate keys but one. Consider using unique keys:
$input = array(
'dataset_1'=>[
'some' =>'...',
'array' => '...', ],
'dataset_2'=>[
'some' =>'...',
'thing' => '...',
'else' => '...',
]
);
$output['whatever'] = array_merge(...array_values($input));
print_r($output);
Output:
Array
(
[whatever] => Array
(
[some] => ...
[array] => ...
[thing] => ...
[else] => ...
)
)
回答2:
You are going to loose the duplicate key 'some' in both examples below.
$a = [
'dataset_1'=>[
'some' =>'...',
'array' => '...', ],
'dataset_2'=>[
'some' =>'...',
'thing' => '...',
'else' => '...',
]
];
// You can use array union operator
$b = $a['dataset_1'] + $a['dataset_2'];
// Or you can use array merge.
$b = array_merge($a['dataset_1'], $a['dataset_2']);
回答3:
One simple way to do this while ensuring no duplicate keys, is to concatenate the parent and child keys with a recursive loop:
$array = [
'dataset_1' => [
'some' => '...',
'array' => '...',
],
'dataset_2' => [
'some' => '...',
'thing' => '...',
'else' => '...',
]
];
$flat_array = [];
foreach($array as $dataset => $data){
foreach($data as $index => $value){
$flat_array[$dataset . '_' . $index] = $value;
}
}
var_export($flat_array);
Outputs:
array (
'dataset_1_some' => '...',
'dataset_1_array' => '...',
'dataset_2_some' => '...',
'dataset_2_thing' => '...',
'dataset_2_else' => '...',
)
If your data gets more complex you can apply this same logic inside a recursive function that can handle many nested layers:
$array = [
'dataset_1' => [
'some' => '...',
'array' => '...',
],
'dataset_2' => [
'some' => '...',
'thing' => '...',
'else' => [
'cheese' => [
'ball' => true,
'wheel' => false
],
],
]
];
function array_flatten ($array)
{
$result = [];
foreach($array as $i => $value)
{
if(!is_array($value)){
$result[$i] = $value;
}else{
// pass array $value back to this same function
$sub_result = array_flatten($value);
foreach($sub_result as $subI => $subV)
{
// concatenate this index with each sub-index
// to get result index for each sub-value
$result[$i . '_' . $subI] = $subV;
}
}
}
return $result;
}
var_export(array_flatten($array));
Outputs:
array (
'dataset_1_some' => '...',
'dataset_1_array' => '...',
'dataset_2_some' => '...',
'dataset_2_thing' => '...',
'dataset_2_else_cheese_ball' => true,
'dataset_2_else_cheese_wheel' => false,
)
回答4:
Actually, I'm doing it by building a target array as template like:
Source array:
$array = [
'dataset_1' => [
'keyFromSourceArray' => 'someValue',
'array' => '...',
];
Destination array:
$array = [
'dataset_somename' => [
'dataset_somename' => [
'some' => 'keyFromSourceArray',
'array' => '...',
],
];
Then, I cylce through the source array, grab the keys, and search and replace it by value in the destination array like:
public function array2api($needle, $array=false, array $path = []) {
foreach ($array as $key => $value) {
$currentPath = array_merge($path, [$key]);
if (is_array($value) && $result = $this->array2api($needle, $value, $currentPath)) {
return $result;
} else if ($value === $needle) {
return $currentPath;
}
}
return false;
}
This is working, but it is - I guess a bit laborious. As I can't fetch the source data from a db, I have to transform it anyway. But I guess theres a much easier solution for it which I didn't get yet.
回答5:
To avoid overwriting duplicate keys, use this. So the duplicate keys in the array will successively take an integer.
// New array
foreach ($array as $key => $sub_array):
foreach ($sub_array as $sub_key => $value):
if (array_key_exists($sub_key,$new_array['whatever'])) {
$i{$sub_key} = !isset($i{$sub_key}) ? 0 : $i{$sub_key};
$sub_key = $sub_key . ++$i{$sub_key};
}
$new_array['whatever'][$sub_key] = $value;
endforeach;
endforeach;
For example:
// Array
$array = [
'dataset_1' => [
'some' => '...',
'array' => '...',
],
'dataset_2' => [
'some' => '...',
'thing' => '...',
'else' => '...',
],
'dataset_3' => [
'some' => '...',
'thing' => '...',
'else' => '...',
]
];
// New array
// the code...
print_r($new_array);
Output:
Array (
[whatever] => Array (
[some] => ...
[array] => ...
[some1] => ...
[thing] => ...
[else] => ...
[some2] => ...
[thing1] => ...
[else1] => ...
[some3] => ...
[thing2] => ...
[else2] => ...
)
)
来源:https://stackoverflow.com/questions/58083342/transform-array-structure-in-php