PHP Can't get the right format for array - php

I got stuck somehow on the following problem:
What I want to achieve is to merge the following arrays based on key :
{"Entities":{"submenu_id":"Parents","submenu_label":"parents"}}
{"Entities":{"submenu_id":"Insurers","submenu_label":"insurers"}}
{"Users":{"submenu_id":"New roles","submenu_label":"newrole"}}
{"Users":{"submenu_id":"User - roles","submenu_label":"user_roles"}}
{"Users":{"submenu_id":"Roles - permissions","submenu_label":"roles_permissions"}}
{"Accounting":{"submenu_id":"Input accounting data","submenu_label":"new_accounting"}}
Which needs to output like this:
[{"item_header":"Entities"},
{"list_items" :
[{"submenu_id":"Parents","submenu_label":"parents"},
{"submenu_id":"Insurers","submenu_label":"insurers"}]
}]
[{"item_header":"Users"},
{"list_items" :
[{"submenu_id":"New roles","submenu_label":"newrole"}
{"submenu_id":"User - roles","submenu_label":"user_roles"}
{"submenu_id":"Roles - permissions","submenu_label":"roles_permissions"}]
}]
[{"item_header":"Accounting"},
{"list_items" :
[{"submenu_id":"Input accounting data","submenu_label":"new_accounting"}]
}]
I have been trying all kinds of things for the last two hours, but each attempt returned a different format as the one required and thus failed miserably. Somehow, I couldn't figure it out.
Do you have a construction in mind to get this job done?
I would be very interested to hear your approach on the matter.
Thanks.

$input = array(
'{"Entities":{"submenu_id":"Parents","submenu_label":"parents"}}',
'{"Entities":{"submenu_id":"Insurers","submenu_label":"insurers"}}',
'{"Users":{"submenu_id":"New roles","submenu_label":"newrole"}}',
'{"Users":{"submenu_id":"User - roles","submenu_label":"user_roles"}}',
'{"Users":{"submenu_id":"Roles - permissions","submenu_label":"roles_permissions"}}',
'{"Accounting":{"submenu_id":"Input accounting data","submenu_label":"new_accounting"}}',
);
$input = array_map(function ($e) { return json_decode($e, true); }, $input);
$result = array();
$indexMap = array();
foreach ($input as $index => $values) {
foreach ($values as $k => $value) {
$index = isset($indexMap[$k]) ? $indexMap[$k] : $index;
if (!isset($result[$index]['item_header'])) {
$result[$index]['item_header'] = $k;
$indexMap[$k] = $index;
}
$result[$index]['list_items'][] = $value;
}
}
echo json_encode($result);

Here you are!
In this case, first I added all arrays into one array for processing.
I thought they are in same array first, but now I realize they aren't.
Just make an empty $array=[] then and then add them all in $array[]=$a1, $array[]=$a2, etc...
$array = '[{"Entities":{"submenu_id":"Parents","submenu_label":"parents"}},
{"Entities":{"submenu_id":"Insurers","submenu_label":"insurers"}},
{"Users":{"submenu_id":"New roles","submenu_label":"newrole"}},
{"Users":{"submenu_id":"User - roles","submenu_label":"user_roles"}},
{"Users":{"submenu_id":"Roles - permissions","submenu_label":"roles_permissions"}},
{"Accounting":{"submenu_id":"Input accounting data","submenu_label":"new_accounting"}}]';
$array = json_decode($array, true);
$intermediate = []; // 1st step
foreach($array as $a)
{
$keys = array_keys($a);
$key = $keys[0]; // say, "Entities" or "Users"
$intermediate[$key] []= $a[$key];
}
$result = []; // 2nd step
foreach($intermediate as $key=>$a)
{
$entry = ["item_header" => $key, "list_items" => [] ];
foreach($a as $item) $entry["list_items"] []= $item;
$result []= $entry;
}
print_r($result);

I would prefer an OO approach for that.
First an object for the list_item:
{"submenu_id":"Parents","submenu_label":"parents"}
Second an object for the item_header:
{"item_header":"Entities", "list_items" : <array of list_item> }
Last an object or an array for all:
{ "Menus: <array of item_header> }
And the according getter/setter etc.

The following code will give you the requisite array over which you can iterate to get the desired output.
$final_array = array();
foreach($array as $value) { //assuming that the original arrays are stored inside another array. You can replace the iterator over the array to an iterator over input from file
$key = /*Extract the key from the string ($value)*/
$existing_array_for_key = $final_array[$key];
if(!array_key_exists ($key , $final_array)) {
$existing_array_for_key = array();
}
$existing_array_for_key[count($existing_array_for_key)+1] = /*Extract value from the String ($value)*/
$final_array[$key] = $existing_array_for_key;
}

Related

PHP/MYSQL Replace text of keys in array of dictionaries

I have a MYSQL query that fetches an array of dictionaries or results which are returned via JSON in an api. In some cases, I would like to change the name of the dictionary keys in the results array.
For example, in the following case:
$var = '[{"player":"Tiger Woods"},{"player":"Gary Player"}]';
I would like to change it to:
$var = '[{"golfer":"Tiger Woods"},{"golfer":"Gary Player"}]'
It is not practical in this case to change the mysql query so I'd just like to replace the word "player" with the word "golfer" for the keys without disturbing the values.
In the above example, I would not want to change Gary Player's name so just using str_replace does not seem like it would work.
Is there a way to change all of the keys from "player" to "golfer" without changing any of the values?
Here is the snippet you can use
$var = '[{"player":"Tiger Woods"},{"player":"Gary Player"}]';
// json decode the json string
$temp = json_decode($var, true);
$temp = array_map(function($item){
// combining key and values
return array_combine(['golfer'], $item);
}, $temp);
print_r($temp);
// or echo json_encode($temp);
Demo.
Some argue that foreach is fastest,
foreach($temp as $k => &$v){
$v = array_combine(['golfer'], $v);
}
print_r($temp);
Demo.
Little hardcoded if more than one keys in single array,
foreach ($temp as $k => &$v){
$v['golfer'] = $v['player'];
unset($v['player']);
}
print_r($temp);
Demo.
Using recursion
function custom($arr, $newKey, $oldKey)
{
// if the value is not an array, then you have reached the deepest
// point of the branch, so return the value
if (!is_array($arr)) {
return $arr;
}
$result = []; // empty array to hold copy of subject
foreach ($arr as $key => $value) {
// replace the key with the new key only if it is the old key
$key = ($key === $oldKey) ? $newKey : $key;
// add the value with the recursive call
$result[$key] = custom($value, $newKey, $oldKey);
}
return $result;
}
$var = '[{"player":"Tiger Woods"},{"player":"Gary Player"}]';
$temp = json_decode($var, true);
$temp = replaceKey($temp, 'golfer', 'player');
print_r($temp);
Demo & source.
Using json way,
function json_change_key($arr, $oldkey, $newkey) {
$json = str_replace('"'.$oldkey.'":', '"'.$newkey.'":', json_encode($arr));
return json_decode($json, true);
}
$temp = json_change_key($temp, 'player', 'golfer');
print_r($temp);
Demo
If you want multiple key replace, here is the trick,
$var = '[{"player":"Tiger Woods", "wins":"10","losses":"3"},{"player":"Gary Player","wins":"7", "losses":6}]';
$temp = json_decode($var, true);
function recursive_change_key($arr, $set)
{
if (is_array($arr) && is_array($set)) {
$newArr = [];
foreach ($arr as $k => $v) {
$key = array_key_exists($k, $set) ? $set[$k] : $k;
$newArr[$key] = is_array($v) ? recursive_change_key($v, $set) : $v;
}
return $newArr;
}
return $arr;
}
$set = [
"player" => "golfers",
"wins" => "victories",
"losses" => "defeats"
];
$temp = recursive_change_key($temp, $set);
print_r($temp);
Demo.
$a = '[{"player":"Tiger Woods"},{"player":"Gary Player"}]';
$array = json_decode($a, true);
foreach($array as $key=>$value){
if(array_keys($value)[0] === "player"){
$array[$key] = ["golfer" => array_values($value)[0]];
};
}
echo json_encode($array);
you can write the value of the key to a new key and then delete the old.
renaming a key called "a" to "b", while keeping the value.
var json = {
"a" : "one"
}
json["b"] = json["a"];
delete json["a"];
for your example, just use this with a loop.
source: https://sciter.com/forums/topic/how-to-rename-the-key-of-json/

Dynamically generating foreach

I'm trying to write a function that do the following :
Let's say i have an array :
$data = array(
array('10','15','20','25'),
array('Blue','Red','Green'),
array('XL','XS')
)
and my result array should be like :
$result = array(
array('10','15','20','25'),
array('Blue','Red','Green','Blue','Red','Green','Blue','Red','Green','Blue','Red','Green')
array('XL','XS','XL','XS','XL','XS','XL','XS','XL','XS','XL','XS','XL','XS','XL','XS','XL','XS','XL','XS','XL','XS','XL','XS','XL','XS','XL','XS','XL','XS','XL','XS','XL','XS','XL','XS','XL','XS','XL','XS','XL','XS','XL','XS','XL','XS','XL','XS')
)
Im stuck with this because i want a function that is able to do this no matter how much array there is in the first array $data
I have only been able to write this, which is what give the $result array :
foreach($data[2] as $value2){
$result[2][] = $value2;
foreach($data[1] as $value1){
$result[1][] = $value1;
foreach($data[0] as $value0){
$result[0][] = $value0;
}
}
}
After a few research, it seems that a recursive function is the way to go in order to dynamically generate those foreach but i can't get it to work.
Thanks for your help.
This is dynamic:
$result[] = array_shift($data);
foreach($data as $value) {
$result[] = call_user_func_array('array_merge',
array_fill(0, count($result[0]), $value));
}
Get and remove the first element from original
Loop remaining elements and fill result with values X number of values in first element
Since the elements were arrays merge them all into result
If modifying the original is unwanted, then use this method:
$result[] = reset($data);
while($value = next($data)) {
$result[] = call_user_func_array('array_merge',
array_fill(0, count($result[0]), $value));
}
just use array_fill and array_merge functions
$result = array(
$data[0],
array_merge(...array_fill(0,count($data[0]), $data[1])),
array_merge(...array_fill(0,count($data[0])*count($data[0]), $data[2]))
);
print_r($result);
demo on eval.in

How do I get the commun results in a for loop in a unknown array length PHP

I have a array of dates, I would like to get all values that are in all of them, thats my example:
$array = [
{"d1":["2016-01-04","2016-01-11","2016-01-18","2016-01-25","2016-02-01"]},
{"d2":["2016-01-05","2016-01-11","2016-01-19","2016-01-25","2015-12-12"]},
{"d3":["2016-01-05","2016-01-11","2016-01-25"]},
{"d4":["2016-01-04","2016-01-11","2016-01-25"]}
]
As result:
$result = ["2016-01-11", ,"2016-01-25"];
Here is a working example (can be optimized, but it should work):
$array = json_decode('[
{"d1":["2016-01-04","2016-01-11","2016-01-18","2016-01-25","2016-02-01"]},
{"d2":["2016-01-05","2016-01-11","2016-01-19","2016-01-25","2015-12-12"]},
{"d3":["2016-01-05","2016-01-11","2016-01-25"]},
{"d4":["2016-01-04","2016-01-11","2016-01-25"]}
]');
$allArrays = array();
foreach ($array as $object) {
foreach ($object as $datesArray) {
array_push($allArrays, $datesArray);
}
}
$sharedDates = call_user_func_array('array_intersect',$allArrays);
var_dump($sharedDates);

A better way to flatten an array in PHP

I require the array keys to be maintained, with a number appended to the key to make it unique when flattening an array.
Example input:
$array = array(
array("name"=>"bob", "age"=>32, "third_param"=>"something"),
array("name"=>"ted", "age"=>57, "third_param"=>"something else"),
array("name"=>"ned", "age"=>103, "third_param"=>"another something"),
);
Required output:
$array = array(
"name-1"=>"bob",
"age-1"=>32,
"third_param-1"=>"something",
"name-2"=>"ted",
"age-2"=>57,
"third_param-2"=>"something else",
"name-3"=>"ned",
"age-3"=>103,
"third_param-3"=>"another something"
);
I was able to figure out how to do it, but my solution is slow and messy. There has got to be a better way.
Here's my current function:
function flatten_array($array, $flat = array()) {
foreach($array as $k=>$v){
$k = strval($k);
if(!is_array($v)){
$i = 0;
while(true){
$i++;
$key = $k."-".strval($i);
if(!isset($flat[$key])) break;
}
$flat[$key] = $v;
}else{
$flat = flatten_array($v, $flat);
}
}
return $flat;
}
Here's an example usage: http://3v4l.org/6QVj0/
(Hit the execute button, and then have a look at the "Performance" tab.
This takes a long time and has timed-out on me when testing it on real data, however it does produce the result I need. What can I do to this to make it quicker and not take up so much memory?
$ar = array();
foreach ($array as $i => $items) {
foreach ($items as $key => $value) {
$ar[$key.'-'.($i+1)] = $value;
}
}

Compare and replace values in array

I need compare 2 arrays , the first array have one order and can´t change , in the other array i have different values , the first array must compare his id with the id of the other array , and if the id it´s the same , take the value and replace for show all in the same order
For Example :
$array_1=array("1a-dogs","2a-cats","3a-birds","4a-people");
$array_2=array("4a-walking","2a-cats");
The Result in this case i want get it´s this :
"1a-dogs","2a-cats","3a-birds","4a-walking"
If the id in this case 4a it´s the same , that entry must be modificate and put the value of other array and stay all in the same order
I do this but no get work me :
for($fte=0;$fte<count($array_1);$fte++)
{
$exp_id_tmp=explode("-",$array_1[$fte]);
$cr_temp[]="".$exp_id_tmp[0]."";
}
for($ftt=0;$ftt<count($array_2);$ftt++)
{
$exp_id_targ=explode("-",$array_2[$ftt]);
$cr_target[]="".$exp_id_targ[0]."";
}
/// Here I tried use array_diff and others but no can get the results as i want
How i can do this for get this results ?
Maybe you could use the array_udiff_assoc() function with a callback
Here you go. It's not the cleanest code I've ever written.
Runnable example: http://3v4l.org/kUC3r
<?php
$array_1=array("1a-dogs","2a-cats","3a-birds","4a-people");
$array_2=array("4a-walking","2a-cats");
function getKeyStartingWith($array, $startVal){
foreach($array as $key => $val){
if(strpos($val, $startVal) === 0){
return $key;
}
}
return false;
}
function getMergedArray($array_1, $array_2){
$array_3 = array();
foreach($array_1 as $key => $val){
$startVal = substr($val, 0, 2);
$array_2_key = getKeyStartingWith($array_2, $startVal);
if($array_2_key !== false){
$array_3[$key] = $array_2[$array_2_key];
} else {
$array_3[$key] = $val;
}
}
return $array_3;
}
$array_1 = getMergedArray($array_1, $array_2);
print_r($array_1);
First split the 2 arrays into proper key and value pairs (key = 1a and value = dogs). Then try looping through the first array and for each of its keys check to see if it exists in the second array. If it does, replace the value from the second array in the first. And at the end your first array will contain the result you want.
Like so:
$array_1 = array("1a-dogs","2a-cats","3a-birds","4a-people");
$array_2 = array("4a-walking","2a-cats");
function splitArray ($arrayInput)
{
$arrayOutput = array();
foreach ($arrayInput as $element) {
$tempArray = explode('-', $element);
$arrayOutput[$tempArray[0]] = $tempArray[1];
}
return $arrayOutput;
}
$arraySplit1 = splitArray($array_1);
$arraySplit2 = splitArray($array_2);
foreach ($arraySplit1 as $key1 => $value1) {
if (array_key_exists($key1, $arraySplit2)) {
$arraySplit1[$key1] = $arraySplit2[$key1];
}
}
print_r($arraySplit1);
See it working here:
http://3v4l.org/2BrVI
$array_1=array("1a-dogs","2a-cats","3a-birds","4a-people");
$array_2=array("4a-walking","2a-cats");
function merge_array($arr1, $arr2) {
$arr_tmp1 = array();
foreach($arr1 as $val) {
list($key, $val) = explode('-', $val);
$arr_tmp1[$key] = $val;
}
foreach($arr2 as $val) {
list($key, $val) = explode('-', $val);
if(array_key_exists($key, $arr_tmp1))
$arr_tmp1[$key] = $val;
}
return $arr_tmp1;
}
$result = merge_array($array_1, $array_2);
echo '<pre>';
print_r($result);
echo '</pre>';
This short code works properly, you'll get this result:
Array
(
[1a] => dogs
[2a] => cats
[3a] => birds
[4a] => walking
)

Categories