Build array of keys and values? - php

Im trying to build a json array in php with this structure:
[{"id":"name last name",
"id":"name last name",
"id":"name last name"
}]
where the id key is always a different number, not only id string
Im trying to do this:
for ($i = 0; $i < count($array); $i++){
//$namesArray[] = array($array[$i]["id"] =>$array[$i]["name"].
// " ".$array[$i]["last"]." ".$array[$i]["name"]);
$namesArray[] = array_fill_keys(
$array[$i]["id"],
$array[$i]["name"]." ".
$array[$i]["last"]." ".
$array[$i]["name"]
);
}
echo json_encode($namesArray);
With the commented lines I get something like this:
[{"id":"name last name"},
{"id":"name last name"}
]
But I dont want that, I want all keys and values in a single array.
Thanks.

Keep your code clean
$array = [];
$array[] = ['id'=>3 , 'name'=>'H', 'last'=>'bensiali' ];
$array[] = ['id'=>4 , 'name'=>'Simon', 'last'=>'Says' ];
$array[] = ['id'=>5 , 'name'=>'Mohammed', 'last'=>'Ali' ];
$val = [];
foreach ($array as $key => $value) {
$val[$value['id']] = sprintf("%s %s" , $value['name'] , $value['last']);
}
echo json_encode($val);
And output will be:
{"3":"H bensiali","4":"Simon Says","5":"Mohammed Ali"}

Here is how you can do it:
// sample data
$array = array(
array("id" => 1, "name" => "James", "last" => "Last"),
array("id" => 2, "name" => "Micheal", "last" => "Jackson"),
);
// create empty object (associative array)
$obj = (object) array();
// add key/value pairs to that object
foreach ($array as $row) {
$obj->$row["id"] = $row["name"] . " " . $row["last"];
}
// wrap object in a single-element array
$result = array($obj);
// output to JSON string
echo json_encode($result, JSON_PRETTY_PRINT);
Output:
[
{
"1": "James Last",
"2": "Micheal Jackson"
}
]

You can use functional approach to fill desired array with array_reduce:
$array = [
['id' => 1, 'name' => 'name1', 'last' => 'last1'],
['id' => 2, 'name' => 'name2', 'last' => 'last2'],
['id' => 3, 'name' => 'name3', 'last' => 'last3'],
];
$newArray = array_reduce($array, function($carry, $item) {
$carry[$item['id']] = $item["name"]." ".
$item["last"]." ".
$item["name"];
return $carry;
});
var_dump($newArray);
And output will be:
array(3) {
[1]=>
string(17) "name1 last1 name1"
[2]=>
string(17) "name2 last2 name2"
[3]=>
string(17) "name3 last3 name3"
}

Related

Convert flat array into a 3d array creating new grouping rows on each non-numeric value

I need to group values in my flat array so that each non-integer value starts a new group/row in my result array and every integer value encountered until the next occurring non-integer should be pushed into a subarray in the respective group/row.
Input:
$unitsList = [
"Aulas Gratuitas",
"149",
"151",
"153",
"Módulo 0",
"964",
"989",
"Módulo 1",
"985",
"1079",
"1001",
"1003"
"Módulo 2",
"1009"
];
Current code:
$newArr = array();
foreach( $unitsList as $item ) {
if( !is_numeric($item) ) {
$title = array( "title" => $item, "units" => "" );
array_push( $newArr, $title);
} elseif ( is_numeric($item) ) {
$number = $item;
array_push( $newArr, $number);
}
}
Current result:
[
[
"title" => "Aulas Gratuitas",
"units" => ""
]
"149",
"151",
"153",
[
"title" => "Módulo 0",
"units" => ""
],
"964",
"989",
[
"title" => 'Módulo 1',
"units" => ""
],
"985",
"1079",
"1001",
"1003"
[
"title" => 'Módulo 2',
"units" => ''
],
"1009"
]
As you can see, I am having a hard time adding the numbers into the "units" key.
Desired result:
[
[
"title" => "Aulas Gratuitas",
"units" => ["149", "151", "153"]
],
[
"title" => 'Módulo 0',
"units" => ["964", "989"]
],
[
"title" => 'Módulo 1',
"units" => ["985", "1079", "1001", "1003"]
],
[
"title" => "Módulo 2",
"units" => ["1009"]
]
]
So that you don't need to keep track of first level indexes, use a reference variable and push related data into that AFTER pushing the new row into the result array.
Code: (Demo)
$result = [];
foreach ($array as $value) {
if (!ctype_digit($value)) {
unset($units);
$units = [];
$result[] = ['title' => $value, 'units' => &$units];
} else {
$units[] = $value;
}
}
var_export($result);
unset() is used to destroy the reference to the previous group, otherwise newly pushed data would be sent to two (or more) places in the result array.
Reference variables have a default value of null. If your title values are guaranteed to be followed by an integer/unit value, then $units = []; can be removed. If you have a title and then another title there will be no data for the former title group. With the explicit array declaration, the group will have an empty units array instead of null.
Related questions answered with the same general technique:
Group array of objects into deeper parent-child structure
Split flat array into grouped subarrays containing values from consecutive key in the input array
How to split a string by repeated characters in PHP?
If you are running PHP7.3 or higher (and by this point you definitely should be) AND you are intimidated/mystified by using a reference variable, then you can leverage array_key_last() to locate the latest created array row.
Code: (Demo)
$result = [];
foreach ($array as $value) {
if (!ctype_digit($value)) {
$result[] = ['title' => $value, 'units' => []];
} else {
$result[array_key_last($result)]['units'][] = $value;
}
}
var_export($result);
Items in the given list aren't regular. The first item has three units, and the second has two units. We cannot convert them into the expected structure without controlling the type of each item. My solution is below. I added explanations as a comment line.
$values = array(
"string",
11111,
22222,
33333,
"string_2",
44444,
55555
);
$formattedArray = [];
$index = -1;
foreach ($values as $value) {
// If the value is a string, create the new array structure item and assign the title
if (is_string($value)) {
$index++;
$formattedArray[$index]['title'] = $value;
$formattedArray[$index]['units'] = [];
// The rest of the code in "foreach scope" is for integer values, so skip the remaining part
continue;
}
// If the following line is executing, the value is an integer
// Push the value to the current item's units
$formattedArray[$index]['units'][] = $value;
}
var_dump($formattedArray);
$originalArray = ['a', 1, 2, 3, 'b', 4, 5, 6];
function formatArray($input) {
$output = [];
foreach($input as $inputRow) {
if (is_string($inputRow)) {
$output[] = ['title' => $inputRow, 'units' => []];
} elseif (count($output)) {
$output[count($output)-1]['units'][] = $inputRow;
}
}
return $output;
}
var_dump(formatArray($originalArray));
Note that your numbers after the title CANNOT be strings, otherwise this function will recognize it as new titles.
This code will output:
array(2) {
[0]=>
array(2) {
["title"]=>
string(1) "a"
["units"]=>
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}
}
[1]=>
array(2) {
["title"]=>
string(1) "b"
["units"]=>
array(3) {
[0]=>
int(4)
[1]=>
int(5)
[2]=>
int(6)
}
}
}
Approach: loop over values in array, check for value if its converted to int is equal to 0, So group by that key, otherwise accumelate they next elements.
<?php
$unitsList = [ "Aulas Gratuitas", "149", "151", "153", "Módulo 0", "964", "989", "Módulo 1", "985", "1079", "1001", "1003", "Módulo 2", "1009" ];
$result = [];
foreach ($unitsList as $key => $value) {
if(intval($value)==0){
$result[] = ['title' => $value, 'units' => []];
}else{
$result[count($result)-1]['units'][] = $value;
}
}
print_r(array_values($result));
?>

Convert an array to multidimensional array

I have an array that looks something like this:
array:2 [
"test1_test2_test3" => "result"
"category_slug" => "the_slug"
]
What I need to do is convert it to a multidimensional array that would look something like this:
array:2 [
"test1" => [
"test2" => [
"test3" => "result"
]
]
"category" => [
"slug" => "the_slug"
]
]
I know that I can explode on the key to get an array but am unsure of how to then go from this to end up with the final result.
EDIT The array looks like that initially because it's being pulled from request parameters: http://url.com?test1.test2.test3=result&category.slug=the_slug and Laravel auto converts it to an array.
A simple solution:
$result = [];
foreach ($array as $key => $value) {
foreach (array_reverse(explode('_', $key)) as $key_part) {
$value = [$key_part => $value];
}
$result += $value;
}
If you need to handle several keys with the same parts (such as test1_test2_test3 and test1_test2_test4), replace the last line with:
$result = array_merge_recursive($result, $value);
My approach would be to reverse the array, then loop through the keys and nest them.
The code below should do the trick.
$array = [
"test1_test2_test3" => "result",
"category_slug" => "the_slug"
];
$array = array_map(function ($key, $value) {
$keys = array_reverse(explode('_', $key));
while($key = array_shift($keys)) {
$value = [$key => $value];
}
return $value;
}, array_keys($array), $array);
$array = call_user_func_array('array_merge', $array);
var_dump($array);
/**
array(2) {
["test1"]=>
array(1) {
["test2"]=>
array(1) {
["test3"]=>
string(6) "result"
}
}
["category"]=>
array(1) {
["slug"]=>
string(8) "the_slug"
}
}
*/
One way to go:
$arr = array("test1_test2_test3" => "result", "category_slug" => "the_slug");
$res = array();
foreach($arr as $k=>$v) {
$t = explode("_", $k);
$new_arr = array();
$tmp = $v;
for($i=count($t)-1; $i > 0; $i--) {
$new_arr[$t[$i]] = $tmp;
$tmp = $new_arr;
$new_arr = array();
}
$res[$t[0]] = $tmp;
}
print_r($res);
Result:
Array
(
[test1] => Array
(
[test2] => Array
(
[test3] => result
)
)
[category] => Array
(
[slug] => the_slug
)
)
Looking through the Laravel documentation I found a helper array_set, which means in order to change the key to a multidimensional array I can change the key to use dot notation with str_replace and then use the helper to convert it over:
$array = [
"test1_test2_test3" => "result"
"category_slug" => "the_slug"
]
$new_array = []
foreach($array as $key => $value)
{
$key = str_replace('_', '.', $key);
array_set($new_array, $key, $value);
}
Result:
array:2 [
"test1" => [
"test2" => [
"test3" => "result"
]
]
"category" => [
"slug" => "the_slug"
]
]

PHP foreach returning last row in multidimentional array

I am trying get user value from multidimensional array as
$array = array();
$array["id"] = "1";
$array["name"] = "name1";
$array["country"] = "country1";
$array["id"] = "2";
$array["name"] = "name2";
$array["country"] = "country2";
$array["id"] = "3";
$array["name"] = "name3";
$array["country"] = "country3";
$array["id"] = "4";
$array["name"] = "name4";
$array["country"] = "country4";
foreach($array as $e){
print_r($e);
}
It return me 4name4country4 only
I need to fetch rows like
foreach($array as $e){
$id=$e['id'];
$name=$e['name'];
$country=$e['country'];
echo $id.'/'.$name.'/'.$country.'<br>';
}
but this gives me error as Illegal string offset 'id'
from what I understood about array this should return all values, Please see why this simple array is not working and suggest any way to do it
Currently you are overwriting the keys. Need to add the keys properly. You have to build the array like -
$array[0]["id"] = "1";
$array[0]["name"] = "name1";
$array[0]["country"] = "country1";
$array[1]["id"] = "2";
$array[1]["name"] = "name2";
$array[1]["country"] = "country2";
OR
$array = array(
0 => array('id' => 1, 'name' => 'name1', 'country' => 'country1'),
1 => array('id' => 2, 'name' => 'name2', 'country' => 'country2'),
);
Instead, do it like so you won't have to give array keys manually
$array = array();
$array[] = array("id" => 123, "name" => "Your name", "country" => "UK");
$array[] = array("id" => 1342, "name" => "Your name 2 ", "country" => "UK");
then in foreach do this
foreach($array as $key => $val){
echo $key. ": ".$val['id']. " " . $val['name'];
}
You have to create the multidimensional array like this, right now you're overwriting the array multiple times.
$arrays = [
[0]=>
["id"] => "1",
["name"] => "name1",
["country"] => "country1"
],
[1]=>[
...
]
];
foreach($arrays as $array){
$id=$array['id'];
$name=$array['name'];
$country=$array['country'];
echo $id.'/'.$name.'/'.'$country'.'<br>';
}

Creating new array from 2 existing arrays - one of them is the key other value

My "main" array looks like this - var_dump($main)
[zlec_addresoperator] => and
[filtervalue0] => Test
[filtercondition0] => CONTAINS
[filteroperator0] => 1
[filterdatafield0] => zlec_addres
[zlec_nroperator] => and
[filtervalue1] => SecondVal
[filtercondition1] => CONTAINS
[filteroperator1] => 1
[filterdatafield1] => zlec_nr
I want to build a new array as
array( filterdatafield0 = > filtervalue0 , filterdatafield1 = > filtervalue1)
etc
First of all I decided to filter out what I wan't with the following codes. Creating new arrays to keep the data I wan't, so $arraykeys will contain the filterdatafield.{1,2} values. In this case it will be zlec_addres and zlec_nr.
The second $arrayvalue will keep the filtervalue.{1,2} which is the value for the filter.
$newarray = array();
$arraykeys = array();
$arrayvalue = array();
foreach($_GET as $key => $value):
if(preg_match("/^filterdatafield.{1,2}$/",$key)>0) {
// $key is matched by the regex
$arrayvalue[] = $value;
}
if(preg_match("/^filtervalue.{1,2}$/",$key)>0) {
// $key is matched by the regex
$arraykeys[] = $key;
}
endforeach;
foreach($arraykeys as $a){
$newarray[$a] = $arrayvalue;
}
So the desired output would be
array(
zlec_addres => 'Test', zlec_nr = 'SecondVal'
)
Now it is
array(12) {
["filtervalue0"]=>
array(12) {
[0]=>
string(11) "zlec_addres"
[1]=>
string(7) "zlec_nr"
...
}
["filtervalue1"]=>
array(12) {
[0]=>
string(11) "zlec_addres"
[1]=>
string(7) "zlec_nr"
...
}
$newarray = array();
$arraykeys = array();
$arrayvalue = array();
foreach($_GET as $key => $value){
if(preg_match("/^filterdatafield.{1,2}$/",$key)>0) {
// $key is matched by the regex
$arraykeys[] = $value;
}
if(preg_match("/^filtervalue.{1,2}$/",$key)>0) {
// $key is matched by the regex
$arrayvalues[] = $value;
}
}
$newArray = array_combine($arraykeys, $arrayvalues);
This should work for you:
Just grab your keys which you want with preg_grep() and then array_combine() both arrays together.
<?php
$arr = [
"zlec_addresoperator" => "and",
"filtervalue0" => "Test",
"filtercondition0" => "CONTAINS",
"filteroperator0" => "1",
"filterdatafield0" => "zlec_addres",
"zlec_nroperator" => "and",
"filtervalue1" => "SecondVal",
"filtercondition1" => "CONTAINS",
"filteroperator1" => "1",
"filterdatafield1" => "zlec_nr",
];
$newArray = array_combine(
preg_grep("/^filterdatafield\d+$/", array_keys($arr)),
preg_grep("/^filtervalue\d+$/", array_keys($arr))
);
print_r($newArray);
?>
output:
Array
(
[filterdatafield0] => filtervalue0
[filterdatafield1] => filtervalue1
)

Create an array with dynamic input in PHP

I have to create a array dynamically like I have a method which will pass keys and based on those keys I need to create arrays inside them
Format will be like-
{
"TEST1":{
"140724":[
{
"A":"1107",
"B":4444,
"C":"1129",
"D":"1129"
},
{
"A":"1010",
"B":2589,
"C":"1040",
"D":"1040"
}
],
"140725":[
]
}
}
So how should I frame this logic inside for loop. I am new to php so formatting the same creating trouble.
$json_Created = array("TEST1" => array());
foreach($val as $key=>$value){
array_push($json_created,array($key = array()));
}
The entire array is dynamic, so like I have 140724 ,,, till 140731 (actually date format yymmdd), any amount if numbers can be considered. SO that part is dynamic moreover some dates may be wont have any values and some will have.
So my main point is to develop that logic so that irrespective the
number of inputs , my array formation must be intact.
You can use json_encode with array to do so
$array = array(
"TEST1" => array(
"140724" => array(
array(
"A" => "1107",
"B" => "4444",
"C" => "1129",
"D" => "1129"
),
array (
"A" => "1010",
"B" => "2589",
"C" => "1040",
"D" => "1040"
)
),
"140725" => array(
)
)
);
echo json_encode($array);
Another way to construct array is
$array = array();
$array["TEST1"]["140724"][] = array(
"A" => "1107",
"B" => "4444",
"C" => "1129",
"D" => "1129"
);
$array["TEST1"]["140724"][] = array (
"A" => "1010",
"B" => "2589",
"C" => "1040",
"D" => "1040"
);
$array["TEST1"]["140725"] = array();
echo json_encode($array);
Finally managed to write the code-
$keys_content = array("starttime", "id", "duration", "endtime");
$dates = array();//140724,140725,140726140727
$mainID =“TEST1”;
$arraySuperMain = array();
$arrayMain = array();
for ($j = 0; $j < count($dates); $j++) {
$array_main = array();
$subset = array();
for ($i = 0; $i < count($keys_content); $i++) {
$key = $keys_content[$i];
$subset = array_push_assoc($subset, $key, "Value".$i);
}
$array_main = array_push_assoc($array_main, $dates[$j], $subset);
array_push($arrayMain, $array_main);
}
$createdJSON = array_push_assoc($arraySuperMain, $mainID, $arrayMain);
public static function array_push_assoc($array, $key, $value) {
$array[$key] = $value;
return $array;
}

Categories