convert nested structure to flat key value pairs - php

I have nested structure very similar to folder structure, like:
Array
(
[level_one_1] => Array
(
[level_two_1] => value1
[level_two_2] => valuetwo
[level_two_3] => value_three
)
[level_one_2] => Array
(
[level_two_4] => value1
[level_two_5] => valuetwo
[level_two_6] => value_three
)
[level_one_3] => Array
(
[level_two_2] => valuetwo
[level_two_3] => value_three
)
)
Is it a quick way to covert it to something like this:
Array
(
[level_one_1/level_two_1] => value1
[level_one_1/level_two_2] => valuetwo
[level_one_1/level_two_3] => value_three
[level_one_2/level_two_4] => value1
[level_one_2/level_two_5] => valuetwo
[level_one_2/level_two_6] => value_three)
[level_one_3/level_two_2] => valuetwo
[level_one_3/level_two_3] => value_three
)
Slash between levels would be separator - it could anything. Also it would be dynamic numbers of levels.
Is it a way to do so by using predefined array* functions ? with recursion ?

Something like this. Untested, but should help you get started in the right direction:
$myArray = array(
'level_one_1' => array(
'level_two_1' => 'value1',
'level_two_2' => 'valuetwo',
'level_two_3' => 'value_three'
),
'level_one_2' => array(
'level_two_4' => 'value1',
'level_two_5' => 'valuetwo',
'level_two_6' => 'value_three'
),
'level_one_3' => array(
'level_two_2' => 'valuetwo',
'level_two_3' => 'value_three'
));
$ritit = new RecursiveIteratorIterator(new RecursiveArrayIterator($myArray));
$result = array();
foreach ($ritit as $leafValue) {
$keys = array();
foreach (range(0, $ritit->getDepth()) as $depth) {
$keys[] = $ritit->getSubIterator($depth)->key();
}
$result[ join('/', $keys) ] = $leafValue;
}

Related

How to add element to advanced array inside foreach loop

I am trying to add my data to my array inside my foreach loop.
I have almost done it successfully, except the array is too in-depth.
It's showing array->array->{WHAT I WANT}
When I need array->{WHAT I WANT}
Example, I'm needing it to be like:
Array
(
[home] => Array
(
[0] => Dashboard\Main#index
[1] => GET
)
[home/] => Array
(
[0] => Dashboard\Main#index
[1] => GET
)
)
When at the moment, it's showing:
Array
(
[0] => Array
(
[services/content-writing] => Array
(
[0] => Dashboard\Services#contentwriting
[1] => GET
)
)
[1] => Array
(
[services/pbn-links] => Array
(
[0] => Dashboard\Services#pbnlinks
[1] => GET
)
)
)
The code I'm currently using inside my foreach loop is:
$realArray = array();
// Services exist
if($services)
{
// Sort them into our array
foreach ($services as $service) {
$servicePageName = $service->page_name;
$serviceName = str_replace(' ', '', strtolower($service->name));
$realArrayNew = array(
"services/$servicePageName" => ["Dashboard\Services#$serviceName", 'GET']
);
array_push($realArray, $realArrayNew);
//'home' => ['Dashboard\Main#index', 'GET'],
}
}
return $realArray;
The servicePageName variable must be the key field on the realArray to get the results you want.
I'm presuming you input object array looks something like this:
[
(int) 0 => object(stdClass) {
name => 'contentwriting'
page_name => 'content-writing'
},
(int) 1 => object(stdClass) {
name => 'pbnlinks'
page_name => 'pbn-links'
}
]
If we do this:
$realArray = [];
if ($services) {
foreach ($services as $service) {
$servicePageName = $service->page_name;
$serviceName = str_replace(' ', '', strtolower($service->name));
$realArray["services/$servicePageName"] = [
0 => "Dashboard\Services#$serviceName",
1 => "GET"
];
}
}
This is what we get on realArray:
[
'services/content-writing' => [
(int) 0 => 'Dashboard\Services#contentwriting',
(int) 1 => 'GET'
],
'services/pbn-links' => [
(int) 0 => 'Dashboard\Services#pbnlinks',
(int) 1 => 'GET'
]
]
This portion of the code inserts a new subarray to your main array:
$realArrayNew = array(
"services/$servicePageName" => ["Dashboard\Services#$serviceName", 'GET']
);
array_push($realArray, $realArrayNew);
Replace it all with:
$realArray["services/$servicePageName"] = ["Dashboard\Services#$serviceName", 'GET'];
That way your top level will have service names as keys.

How to change date format in multidimensional array and iterate all array with key

I have a multidimensional array with key and value and some key is empty also. Then I want to set a value for internal not empty array.
$oldArray = array("Lexus LS600" => array(),
"Toyota Alphard" => array(),
"Benz S550" => array(0 => array(
"card_no" => "G2FPCBS3",
"travel_date" => "2020-09-10"
"travel_time" => "16:15:00",
"car_id" => 12,
"return_time" => "17:25")),
"BMW X6" => array());
I had this array but I want to set return_time 00:00 all over array. I tried foreach loop but foreach is remove empty array but I want empty array also.
I want this type array:-
$newArray = array("Lexus LS600" => array(),
"Toyota Alphard" => array(),
"Benz S550" => array(0 => array(
"card_no" => "G2FPCBS3",
"travel_date" => "2020-09-10"
"travel_time" => "16:15:00",
"car_id" => 12,
"return_time" => "00:00")),
"BMW X6" => array());
Try this foreach again, I think it will solve your problem if I understood you correctly.
foreach ($arrays as $key => $values) {
if (is_array($values)) {
if (count($values)) {
foreach ($values as $index => $data) {
$arrays[$key][$index]['return_time'] = "00:00";
}
} else {
$arrays[$key] = $values;
}
}
}
It will change return_time to "00:00" and also retain the empty index to your array.
array_walk_recursive() is very suitable for this.
$oldArray = array("Lexus LS600" => array(),
"Toyota Alphard" => array(),
"Benz S550" => array(0 => array(
"card_no" => "G2FPCBS3",
"travel_date" => "2020-09-10",
"travel_time" => "16:15:00",
"car_id" => 12,
"return_time" => "17:25")),
"BMW X6" => array());
$keySearch = "return_time";
$replaceWith = "00:00";
array_walk_recursive(
$oldArray,
function(&$val,$key) use($keySearch,$replaceWith){
if($key == $keySearch) $val = $replaceWith;
}
);
var_export($oldArray);
Output:
array (
'Lexus LS600' =>
array (
),
'Toyota Alphard' =>
array (
),
'Benz S550' =>
array (
0 =>
array (
'card_no' => 'G2FPCBS3',
'travel_date' => '2020-09-10',
'travel_time' => '16:15:00',
'car_id' => 12,
'return_time' => '00:00',
),
),
'BMW X6' =>
array (
),
)
Use two foreach loops to traverse the limited-depth array and make all values modifiable by reference (& before the variable). In doing so, you don't need to create a separate array, just update the input array. It is SUPER easy to read and maintain.
Code: (Demo)
foreach ($array as &$cars) {
foreach ($cars as &$entry) {
if ($entry) {
$entry["return_time"] = "00:00";
}
}
}
var_export($array);
Output:
array (
'Lexus LS600' =>
array (
),
'Toyota Alphard' =>
array (
),
'Benz S550' =>
array (
0 =>
array (
'card_no' => 'G2FPCBS3',
'travel_date' => '2020-09-10',
'travel_time' => '16:15:00',
'car_id' => 12,
'return_time' => '00:00',
),
),
'BMW X6' =>
array (
),
)

How can I get a key value from two arrays on match?

I have 2 arrays, I'm trying to find any matches and return 'url from $array_full.
I tried array_intersect($array_full, $array_ids), but it doesn't work.
$array_full = array
(
Array
(
'#attributes' => Array
(
'topicid' => 102000,
'url' => 'Velkommen.htm',
'alias' => 'Velkommen'
)
),
Array
(
'#attributes' => Array
(
'topicid' => 130313,
'url' => 'WStation/WAS_Indstillinger.htm',
'alias' => 'WAS_Indstillinger'
)
),
Array
(
'#attributes' => Array
(
'topicid' => 130315,
'url' => 'SPedestal/Applikationer/LoadSharing/Indstillinger.htm',
'alias' => 'LOS_Indstillinger'
)
),
Array
(
'#attributes' => Array
(
'topicid' => 130312,
'url' => 'WStation/WAS_Indstillinger.htm',
'alias' => 'WAS_Indstillinger'
)
)
);
$array_ids = array('130312', '130315');
I expect to get an array of matched url's, like:
array('WStation/WAS_Indstillinger.htm','SPedestal/Applikationer/LoadSharing/Indstillinger.htm')
A simple couple of foreach loops seems the easiest approach
$results = [];
foreach ( $array_full as $a ) {
foreach ( $a as $item ) {
if ( in_array($item['topicid'], $array_ids) ) {
$results[] = $item['url'];
}
}
}
print_r($results);
RESULT
Array
(
[0] => SPedestal/Applikationer/LoadSharing/Indstillinger.htm
[1] => WStation/WAS_Indstillinger.htm
)
You will have to make foreach inside foreach to find item that is matching to ID.
Something like this (not tested, may contain some typos).
foreach($array_ids as $id) {
foreach($array_full as $key => $fullItem) {
if($fillItem['#attributes']['topicid'] != $id) {
continue;
}
//do what you need with $fullItem array
$key; // this is the key you want
}
}
you can use array_map, in_array to get the URL's
$result = [];
array_map(function($v) use ($array_ids,&$result){
$result[] = in_array($v['#attributes']['topicid'], $array_ids) ? $v['#attributes']['url'] : '';
}, $array_full);
Result:-
echo '<pre>';
print_r(array_filter($result));
Array
(
[2] => SPedestal/Applikationer/LoadSharing/Indstillinger.htm
[3] => WStation/WAS_Indstillinger.htm
)

get array value in another array php foreach

i have an array
Array
(
[0] => Array
(
[folding_knives__no_assist__possession19] => G
[folding_knives__no_assist__possession___length20] =>
[folding_knives__no_assist___open_cary21] => G
[folding_knives__no_assist__open_carry_length22] =>
[folding_knives__no_assist__concealed23] => G
[folding_knives__no_assisted__concealed_length24] =>
[folding_knives__no_assist__concealed_w__ccw_required25] => R
[folding_knives__no_assist__concealed_w__ccw_required_l26] =>
[folding_knives__no_assist___notes27] =>
)
[1] => Array
(
[folding_knives__assisted_opening__possession28] => G
[folding_knives__assisted_opening__possession_length29] =>
[folding_knives__assisted_opening__open_carry30] => G
[folding_knives__assisted_opening__open_carry_length31] =>
[folding_knives__assisted_opening___concealed32] => G
[folding_knives__assisted_opening__concealed_length33] =>
[folding_knives__assisted_opening___concealed_w__ccw_re34] => R
[folding_knives__assisted_opening__concealed_w__ccw_req35] =>
[folding_knives___assisted_opening___notes36] =>
)
)
I already trying to show my array data into another array but cant
foreach ($chunks as $key => $val)
{
$allknife[] = array(
'name'=>$key[0],
'possession'=>$val[0],
'possession_length'=>$val[1]
);
}
Here name'=>$key[0] here will be arry first item key like folding_knives__no_assist__possession19
It should be link this, and you want field count link 1/2/3/4... then you have to use flag logic like, i=0; and i++
$allknife[] = array();
foreach ($chunks as $key => $val)
{
$allknife['name']=>$val['yourvaluesoeshere'],
$allknife['possession']=>$val['yourvaluesoeshere'],
$allknife['possession_length']=>$val['yourvaluesoeshere']
}
Since your arrays have inconsistent key names you can't rely on this an need consistent names first!
Map the array more like this:
array(
0 => array(
'assist' => true,
'open_carry_nr' => 21,
'open_carry_length' => 22
// and so on...
),
2 => array(
'assist' => false,
'open_carry_nr' => 18,
'open_carry_length' => 1337
// and so on...
)
);
Way better practice.

PHP arrays. There must be a simpler method to do this

I have this array in php returned from db
Array
(
[inv_templates] => Array
(
[0] => Array
(
[inven_subgroup_template_id] => 1
[inven_group] => Wires
[inven_subgroup] => CopperWires
[inven_template_id] => 1
[inven_template_name] => CopperWires6G
[constrained] => 0
[value_constraints] =>
[accept_range] => 2 - 16
[information] => Measured Manual
)
[1] => Array
(
[inven_subgroup_template_id] => 1
[inven_group] => Wires
[inven_subgroup] => CopperWires
[inven_template_id] => 2
[inven_template_name] => CopperWires2G
[constrained] => 0
[value_constraints] =>
[accept_range] => 1 - 7
[information] => Measured by Automated Calipers
)
)
)
I need to output this kind of multidimensional stuff
Array
(
[Wires] => Array
(
[inv_group_name] => Wires
[inv_subgroups] => Array
(
[CopperWires] => Array
(
[inv_subgroup_id] => 1
[inv_subgroup_name] => CopperWires
[inv_templates] => Array
(
[CopperWires6G] => Array
(
[inv_name] => CopperWires6G
[inv_id] => 1
)
[CopperWires2G] => Array
(
[inv_name] => CopperWires2G
[inv_id] => 2
)
)
)
)
)
)
I currently do this stuff
foreach ($data['inv_templates'] as $key => $value) {
$processeddata[$value['inven_group']]['inv_group_name'] = $value['inven_group'];
$processeddata[$value['inven_group']]['inv_subgroups'][$value['inven_subgroup']]['inv_subgroup_id'] = $value['inven_subgroup_template_id'];
$processeddata[$value['inven_group']]['inv_subgroups'][$value['inven_subgroup']]['inv_subgroup_name'] = $value['inven_subgroup'];
$processeddata[$value['inven_group']]['inv_subgroups'][$value['inven_subgroup']]['inv_templates'][$value['inven_template_name']]['inv_name'] = $value['inven_template_name'];
$processeddata[$value['inven_group']]['inv_subgroups'][$value['inven_subgroup']]['inv_templates'][$value['inven_template_name']]['inv_id'] = $value['inven_template_id'];
}
return $processeddata;
EDIT : A var_export
array (
'inv_templates' =>
array (
0 =>
array (
'inven_subgroup_template_id' => '1',
'inven_group' => 'Wires',
'inven_subgroup' => 'CopperWires',
'inven_template_id' => '1',
'inven_template_name' => 'CopperWires6G',
'constrained' => '0',
'value_constraints' => '',
'accept_range' => '2 - 16',
'information' => 'Measured Manual',
),
1 =>
array (
'inven_subgroup_template_id' => '1',
'inven_group' => 'Wires',
'inven_subgroup' => 'CopperWires',
'inven_template_id' => '2',
'inven_template_name' => 'CopperWires6G',
'constrained' => '0',
'value_constraints' => '',
'accept_range' => '1 - 7',
'information' => 'Measured by Automated Calipers',
),
),
)
The foreach is almost unreadable. There must be a simpler way
$processeddata = array();
foreach($data['inv_templates'] as $key => $value) {
$group = $value['inven_group'];
$processeddata[$group]['inv_group_name'] = $group;
$subgroup = &$processeddata[$group]['inv_subgroups'][$value['inven_subgroup']];
$subgroup['inv_subgroup_id'] = $value['inven_subgroup_template_id'];
$subgroup['inv_subgroup_name'] = $value['inven_subgroup'];
$template = $value['inven_template_name'];
$subgroup['inv_templates'][$template]['inv_name'] = $template;
$subgroup['inv_templates'][$template]['inv_id'] = $value['inven_template_id'];
}
return $processeddata;
Untested code. This structures the array in a multidimensional way, and then uses array_merge_recursive to merge them with the already processed data.
if (!isset($processeddata[$value['inven_group']]))
$processeddata[$value['inven_group']] = array();
$processeddata[$value['inven_group']] = array_merge_recursive(
$processeddata[$value['inven_group']],
array(
'inv_group_name' => $value['inven_group'],
'inv_subgroups' => array(
$value['inven_subgroup'] => array(
'inv_subgroup_id' => $value['inven_subgroup_template_id'],
'inv_subgroup_name' => $value['inven_subgroup'],
'inv_templates' => array(
$value['inven_template_name'] => array(
'inv_name' => $value['inven_template_name'],
'inv_id' => $value['inven_template_id'],
),
),
),
),
)
);
I find this format usually works for me. You could do it more efficient, I've just never cared :D
I started traversing at $yourArray['inv_templates'] though.
function groupToStructure(array $rows, array $keys) {
$tree = array();
$keys = array_reverse($keys);
foreach ($rows as $row) {
$subTree = array($row);
foreach ($keys as $key) {
$subTree = array($row[$key] => $subTree);
}
$tree = array_merge_recursive($tree, $subTree);
}
return $tree;
}
print_r(groupToStructure($rows, array('inven_group', 'inven_subgroup', 'inven_template_name')));

Categories