PHP: Generate JSON from array in a specific way - php

I would like to create a JSON from Array in a specific way. My array looks like this at the beginning:
array(2) {
[22]=>
array(8) {
["factor"]=>
array(2) {
[0]=>
string(2) "12"
[1]=>
string(1) "1"
}
["unit"]=>
array(2) {
[0]=>
string(6) "months"
[1]=>
string(5) "times"
}
["value"]=>
array(2) {
[0]=>
string(3) "2.5"
[1]=>
string(1) "2"
}
["planid"]=>
array(2) {
[0]=>
string(1) "1"
[1]=>
string(1) "1"
}
["position"]=>
array(2) {
[0]=>
string(22) "Test 1"
[1]=>
string(21) "Test 2"
}
["vouchervalue"]=>
array(2) {
[0]=>
string(1) "0"
[1]=>
string(1) "0"
}
["vouchertype"]=>
array(2) {
[0]=>
string(0) ""
[1]=>
string(0) ""
}
["vat"]=>
array(2) {
[0]=>
int(19)
[1]=>
int(19)
}
}
[23]=>
array(8) {
["factor"]=>
array(2) {
[0]=>
string(2) "12"
[1]=>
string(1) "1"
}
["unit"]=>
array(2) {
[0]=>
string(6) "months"
[1]=>
string(5) "times"
}
["value"]=>
array(2) {
[0]=>
string(3) "2.5"
[1]=>
string(1) "2"
}
["planid"]=>
array(2) {
[0]=>
string(1) "1"
[1]=>
string(1) "1"
}
["position"]=>
array(2) {
[0]=>
string(22) "Test 3"
[1]=>
string(21) "Test 4"
}
["vouchervalue"]=>
array(2) {
[0]=>
string(1) "0"
[1]=>
string(1) "0"
}
["vouchertype"]=>
array(2) {
[0]=>
string(0) ""
[1]=>
string(0) ""
}
["vat"]=>
array(2) {
[0]=>
int(19)
[1]=>
int(19)
}
}
}
This is how the JSON looks like:
string(354) "{"factor":[["12","1"],["12","1"]],"unit":[["months","times"],["months","times"]],"value":[["2.5","2"],["2.5","2"]],"planid":[["1","1"],["1","1"]],"position":[["Test 1","Test 2"],["Test 3","Test 4"]],"vouchervalue":[["0","0"],["0","0"]],"vouchertype":[["",""],["",""]],"vat":[[19,19],[19,19]]}"
But I would like to have it this way:
string(214) "{"factor":["12", "1","12","1"],"unit":["months", "times","months","times"],"value":["2.5","2","2.5", "2"],"planid":["1","1","1","1"],"position":["Test 1","Test 2", "Test 3", "Test 4"],"vouchervalue":["0","0","0","0"],"vouchertype":["","","",""],"vat":[19,19,19,19]}"
The idea is that every order can contain more than 1 position that can be used to create a JSON which can be used in the rest of the application (there is a table that uses JSON).
Well, I've no idea how to solve this so I'm happy about any hint :-)

Let us say you have the data in array $a.
$a = array(
array(
'factor'=> array( '12', '1' ),
'unit'=> array( 'months', 'times' ),
'value'=> array( '2.5', '2' ),
'planid'=> array( '1', '1' ),
'position'=> array( 'Test 1', 'Test 2' ),
'vouchervalue'=> array( '0', '0' ),
'vouchertype'=> array( '', '' ),
'vat'=> array( 19, 19 ),
),
array(
'factor'=> array( '12', '1' ),
'unit'=> array( 'months', 'times' ),
'value'=> array( '2.5', '2' ),
'planid'=> array( '1', '1' ),
'position'=> array( 'Test 3', 'Test 4' ),
'vouchervalue'=> array( '0', '0' ),
'vouchertype'=> array( '', '' ),
'vat'=> array( 19, 19),
),
);
This in your example contains two arrays, you want to combine. This is one way:
$b = array();
foreach( $a[0] as $k=>$v ) {
if ( isset( $a[1][$k] ) ) // Add keys in both arrays
$b[$k] = array_merge( $a[0][$k], $a[1][$k] );
else // Add keys in only first array
$b[$k] = $a[0][$k];
}
foreach( $a[1] as $k=>$v ) {
if ( !isset( $a[0][$k] ) ) // Add keys in only second array
$b[$k] = $a[1][$k];
}
echo json_encode( $b );
This iterates through the first array. If the key ('factor', 'unit') is available in both arrays, it merges them otherwise it just adds the array.
Secondly it iterates through the second array and adds the arrays which has not been added in the first pass (if the key was not in the first array).
In your case, the arrays seem to have the same set of keys, and a second pass might not be necessary, but just to be sure...
This is the result:
{"factor":["12","1","12","1"],"unit":["months","times","months","times"],"value":["2.5","2","2.5","2"],"planid":["1","1","1","1"],"position":["Test 1","Test 2","Test 3","Test 4"],"vouchervalue":["0","0","0","0"],"vouchertype":["","","",""],"vat":[19,19,19,19]}
If you do not want the numbers in the json to be string encoded, like "12" but rather 12, add JSON_NUMERIC_CHECK to json_encode
echo json_encode( $b, JSON_NUMERIC_CHECK );
{"factor":[12,1,12,1],"unit":["months","times","months","times"],"value":[2.5,2,2.5,2],"planid":[1,1,1,1],"position":["Test 1","Test 2","Test 3","Test 4"],"vouchervalue":[0,0,0,0],"vouchertype":["","","",""],"vat":[19,19,19,19]}

You're looking for array_merge_recursive(). Per the docs:
array_merge_recursive() merges the elements of one or more arrays together so that the values of one are appended to the end of the previous one. It returns the resulting array.
If the input arrays have the same string keys, then the values for these keys are merged together into an array, and this is done recursively, so that if one of the values is an array itself, the function will merge it with a corresponding entry in another array too. If, however, the arrays have the same numeric key, the later value will not overwrite the original value, but will be appended.
Using the example inputs that #HasseBjork outlined above in his answer (based on your original input):
$a = array(
array(
'factor'=> array( '12', '1' ),
'unit'=> array( 'months', 'times' ),
'value'=> array( '2.5', '2' ),
'planid'=> array( '1', '1' ),
'position'=> array( 'Test 1', 'Test 2' ),
'vouchervalue'=> array( '0', '0' ),
'vouchertype'=> array( '', '' ),
'vat'=> array( 19, 19 ),
),
array(
'factor'=> array( '12', '1' ),
'unit'=> array( 'months', 'times' ),
'value'=> array( '2.5', '2' ),
'planid'=> array( '1', '1' ),
'position'=> array( 'Test 3', 'Test 4' ),
'vouchervalue'=> array( '0', '0' ),
'vouchertype'=> array( '', '' ),
'vat'=> array( 19, 19),
),
);
All you need to do is:
echo json_encode(array_merge_recursive($a[0], $a[1]));

Related

PHP check if certain value in different arrays are the same for all

I have couple of arrays like this
$arrayOne = array (
"name" => 'john',
"position" => 'instructor',
"hired" => '2010',
"department" => 'math',
);
$arrayTwo = array (
"name" => 'smith',
"position" => 'instructor',
"hired" => '2010',
"department" => 'math',
);
$arrayThree = array (
"name" => 'dave',
"position" => 'instructor',
"hired" => '2009',
"department" => 'math',
);
how can I check if these arrays all have the same hired date?
one way would be compare each individual one:
if($arrayOne['hired'] === $arrayTwo['hired']) & if($arrayOne['hired'] === $arrayThree['hired']) & ...
but is there a cleaner way to do this?
Your initial question and subsequent comment are similar but they are attempting to do different things with the data, with different outcomes. The initial as-asked was:
how can I check if these arrays all have the same hired date
And that can be done with the following:
var_dump(count(array_unique(array_column([$arrayOne, $arrayTwo, $arrayThree], 'hired'))));
// or
$combined = [$arrayOne, $arrayTwo, $arrayThree];
$hiredValues = array_column($combined, 'hired');
$hiredValuesUnique = array_unique($hiredValues);
$length = count($hiredValuesUnique);
var_dump($length);
If the count is 1, they are the same, otherwise they aren't.
But, your follow-up comment was
how can I know which ones are the same
To do that, I'd create a new array that is keyed by that value, and foreach over the source arrays, effectively grouping similar ones for you to further act up.
$final = [];
foreach([$arrayOne, $arrayTwo, $arrayThree] as $array){
if(!array_key_exists($array['hired'], $final)){
$final[$array['hired']] = [];
}
$final[$array['hired']][] = $array;
}
var_dump($final);
Which produces:
array(2) {
[2010]=>
array(2) {
[0]=>
array(4) {
["name"]=>
string(4) "john"
["position"]=>
string(10) "instructor"
["hired"]=>
string(4) "2010"
["department"]=>
string(4) "math"
}
[1]=>
array(4) {
["name"]=>
string(5) "smith"
["position"]=>
string(10) "instructor"
["hired"]=>
string(4) "2010"
["department"]=>
string(4) "math"
}
}
[2009]=>
array(1) {
[0]=>
array(4) {
["name"]=>
string(4) "dave"
["position"]=>
string(10) "instructor"
["hired"]=>
string(4) "2009"
["department"]=>
string(4) "math"
}
}
}
I have written the code below:
//Your data
$arrayOne = array (
"name" => 'john',
"position" => 'instructor',
"hired" => '2010',
"department" => 'math',
);
$arrayTwo = array (
"name" => 'smith',
"position" => 'instructor',
"hired" => '2010',
"department" => 'math',
);
$arrayThree = array (
"name" => 'dave',
"position" => 'instructor',
"hired" => '2009',
"department" => 'math',
);
function hiredIsTheSameEverywhere(...$arrays) : bool
{
return count(array_count_values(array_column($arrays, "hired"))) === 1;
}
function whereHiredIsTheSame(...$arrays) : array
{
$return = [];
$count = array_count_values(array_column($arrays, "hired"));
foreach($arrays as $array) {
if($count[$array['hired']] > 1) {
$return[$array['hired']][] = $array;
}
}
return $return;
}
//The output
var_dump(hiredIsTheSameEverywhere($arrayOne, $arrayTwo, $arrayThree));
var_dump(whereHiredIsTheSame($arrayOne, $arrayTwo, $arrayThree));
output:
bool(false)
array(1) {
[2010]=>
array(2) {
[0]=>
array(4) {
["name"]=>
string(4) "john"
["position"]=>
string(10) "instructor"
["hired"]=>
string(4) "2010"
["department"]=>
string(4) "math"
}
[1]=>
array(4) {
["name"]=>
string(5) "smith"
["position"]=>
string(10) "instructor"
["hired"]=>
string(4) "2010"
["department"]=>
string(4) "math"
}
}
}

Echo two multidimensional array with different table

So I have this kind of project to have post divided into several provinces. I have two multidimensional array with table1 and table2, I have been trying to echo it with foreach function and etc but still error. This is my array :
array(2) {
[0]=>
array(1) {
[1]=>
array(2) {
["table1"]=>
array(12) {
[0]=>
string(1) "1"
["id_province"]=>
string(1) "1"
[1]=>
string(13) "Province A"
["nm_province"]=>
string(13) "Province A"
}
["table2"]=>
array(2) {
[0]=>
array(58) {
[0]=>
string(2) "43"
["id_news"]=>
string(2) "43"
[1]=>
string(1) "1"
["id_province"]=>
string(1) "1"
[2]=>
string(23) "News A"
["nm_news"]=>
string(23) "News A"
}
[1]=>
array(58) {
[0]=>
string(3) "123"
["id_news"]=>
string(3) "123"
[1]=>
string(1) "1"
["id_province"]=>
string(1) "1"
[2]=>
string(21) "News B"
["nm_news"]=>
string(21) "News B"
}
}
}
}
[1]=>
array(1) {
[2]=>
array(2) {
["table1"]=>
array(12) {
[0]=>
string(1) "2"
["id_province"]=>
string(1) "2"
[1]=>
string(23) "Province B"
["nm_province"]=>
string(23) "Province B"
}
["table2"]=>
array(2) {
[0]=>
array(58) {
[0]=>
string(2) "44"
["id_news"]=>
string(2) "44"
[2]=>
string(1) "2"
["id_province"]=>
string(1) "2"
[5]=>
string(24) "News A Province B"
["nm_news"]=>
string(24) "News A Province B"
}
[1]=>
array(58) {
[0]=>
string(3) "127"
["id_news"]=>
string(3) "127"
[2]=>
string(1) "2"
["id_province"]=>
string(1) "2"
[5]=>
string(13) "News B Province B"
["nm_news"]=>
string(13) "News B Province B"
}
}
}
}
}
I don't have any idea how to retrieve more than 2 table in my array with. So I repeat again I want to echo this 2 table the 1st province had 2 news and 2nd province also had 2 news, What I want to do is echo this 2 news sorting with province.
Ps. This is my code to show arrays output
<?php
$a=mysql_query("select * from province");
while($m1=mysql_fetch_array($a)){
$result[]=$m1;
}
$output=[];
$i=0;
foreach($result as $r){
$b=$r['id_province'];
$c=mysql_query("select * from news where id_province=".$b);
$output[$i][$b]['table1']=$r;
$dummy=[];
while($response = mysql_fetch_array($c)){
$dummy[] = $response;
}
$output[$i][$b]['table2']=$dummy;
$i++;
}
Thanks For helping guys.
update below code it will work for you..
foreach($result as $r){
$b=$r['id_province'];
$c=mysql_query("select * from news where id_province=".$b);
$output[$i]['table1']=$r;
$dummy=[];
while($response = mysql_fetch_array($c)){
$dummy[] = $response;
}
$output[$i]['table2']=$dummy;
$i++;
}
Here i have removed extra [$b] from $output array.
Now copy below code to print array.
foreach($output as $out){
$table1= $out['table1'];
$table2= $out['table2'];
echo $table1['nm_provinsi'].'<br>';
echo 'Data from table 2';
foreach($table2 as $tab2){
echo "\t".$tab2['nm_berita'].'<br>';
}
}
I'd say you'd need to clean up your array first to make sure you are trying to reference the right object, you seem to have everything duplicated with an index and a key in the array.
[0]=>"123",
["id_news"]=>"123",
[1]=>"1",
["id_province"]=>"1",
[2]=>"News B",
["nm_news"]=>"News B",
Edit
I've broken down your array so you can see what I mean clearly
array(
'table1' => array(
'0' => 1,
'id_province' => 1,
'1' => 'Province A',
'nm_province' => 'Province A'
),
'table2' => array(
array(
'0' => '43',
'id_news' => '43',
'1' => '1',
'id_province' => '1',
'2' => 'News A',
'nm_news' => 'News A'
),
array(
'0' => '123',
'id_news' => '123',
'1' => 1,
'id_province' => '1',
'2' => 'New B',
'nm_news' => 'News B')
)
),
array(
'table1' => array(
'0' => "2",
'id_province' => "2",
'1' => "Province B",
'nm_province' => 'Province B'
),
'table2' => array(
array(
'0'=>'44',
'id_news' => '44',
'2' => '2',
'id_province' => '2',
'5' => 'News A Province B',
'nm_news' => 'News A Province B'
),
array(
'0'=>'127',
'id_news' => '127',
'2'=>'2',
'id_province' => '2',
'5' => 'News B Province B',
'nm_news' => 'News B Province B'
)
)
)
Try
$c=mysql_query("select * from news where id_province='$b'");

add elements of associative array with same key

I have associative array like this
$min_stats=
array(2)
{
[0]=> array(3)
{
["minute"]=> object(MongoInt64)#13 (1)
{
["value"]=> string(8) "10"
}
["add"]=> object(MongoInt64)#14 (1)
{
["value"]=> string(1) "9"
}
["tag"]=> object(MongoInt64)#15 (1)
{
["value"]=> string(1) "4"
}
}
[1]=> array(3)
{
["minute"]=> object(MongoInt64)#13 (1)
{
["value"]=> string(8) "11"
}
["add"]=> object(MongoInt64)#14 (1)
{
["value"]=> string(1) "9"
}
["tag"]=> object(MongoInt64)#15 (1)
{
["value"]=> string(1) "5"
}
}
} Array
Now I want to combine all the key-value pair in the array to get one array.
The resulting array should be
array(11)
{
["minute"]=> int(21)
["add"]=> int(18)
["tag"]=> int(9)
} Array
so for what I have written is
foreach ($min_stats as $k=>$subArray) {
foreach ($subArray as $id=>$value) {
$sumArray[$id]+=$value;
}
}
but its not giving me correct results, I don't know what I'm doing wrong?
The $value is coming as 2 means its just counting the elements in the subarray.
Thanks in advance for the help.
You can do it like this:
$finalArr = array();
foreach($array as $k1 => $v1){
foreach($v1 as $k2=>$v2){
if(!isset($finalArr[$k2])){
$finalArr[$k2] = 0;
}
$finalArr[$k2] += $v2['value'];
}
}
print_r($finalArr);
Output:
Array
(
[minute] => 21
[add] => 18
[tag] => 9
)
Easy copy array for testing:
$array = array(
array(
'minute' => array(
'value' => '10'
),
'add' => array(
'value' => '9'
),
'tag' => array(
'value' => '4'
),
),
array(
'minute' => array(
'value' => '11'
),
'add' => array(
'value' => '9'
),
'tag' => array(
'value' => '5'
),
)
);

complicate array push to the first index

I have multidimensional array which is create like
$column = array(
"person#1"=> array ("name"=>"Leon" , "Age"=>"19" ),
"person#2"=> array ("name"=>"Gary" , "Age"=>"31" ),
"person#3"=> array ("name"=>"May" , "Age"=>"25" )
)
Now, what I want is to push something like
"person#4"=> array ("name"=>"Tony" , "Age"=>"28" )
to the first place of array column.
I had look into
array_unshift($column, array("person#1"=> array ("name"=>"Tony" , "Age"=>"28" ));
it did replace the array and variable with my array, but always indexed with '0' and not person#4 as expect
Why not do a simple $new_person + $column ?
Use array_merge():
<?php
header('Content-Type: text/plain');
$column = array(
"person#1"=> array ("name"=>"Leon" , "Age"=>"19" ),
"person#2"=> array ("name"=>"Gary" , "Age"=>"31" ),
"person#3"=> array ("name"=>"May" , "Age"=>"25" )
);
$column = array_merge(array( "person#4" => array ("name" => "Tony" , "Age" => "28" )), $column);
var_dump($column);
?>
Shows:
array(4) {
["person#4"]=>
array(2) {
["name"]=>
string(4) "Tony"
["Age"]=>
string(2) "28"
}
["person#1"]=>
array(2) {
["name"]=>
string(4) "Leon"
["Age"]=>
string(2) "19"
}
["person#2"]=>
array(2) {
["name"]=>
string(4) "Gary"
["Age"]=>
string(2) "31"
}
["person#3"]=>
array(2) {
["name"]=>
string(3) "May"
["Age"]=>
string(2) "25"
}
}

How can you make a multidimensional array unique? [duplicate]

This question already has answers here:
Filter/Remove rows where column value is found more than once in a multidimensional array
(4 answers)
Closed 9 months ago.
I've got a multidimensional array setup like the following:
array(
[0]=>
array(
["name"]=> "Foo"
["slug"]=> "Bar"
)
[1]=>
array(
["name"]=> "Foo"
["slug"]=> "Bar"
)
[2]=>
array(
["name"]=> "Test 1"
["slug"]=> "test-1"
)
[3]=>
array(
["name"]=> "Test 2"
["slug"]=> "test-2"
)
[4]=>
array(
["name"]=> "Test 3"
["slug"]=> "test-3"
)
)
What would be the best way to search through the area for duplicates values in "name" and remove them, so that each value in the multidimensional array is unique?
Thanks in advance!
You can use an associative array.
$temp_array = array();
foreach ($array as &$v) {
if (!isset($temp_array[$v['name']]))
$temp_array[$v['name']] =& $v;
}
This creates a temporary array, using $v['name'] as the key. If there is already an element with the same key, it is not added to the temporary array.
You can convert the associative array back to a sequential array, using
$array = array_values($temp_array);
Example code and output: http://codepad.org/zHfbtUrl
Since everyone given alternatives, here's a solution to the problem at-hand. Sometimes we have to work with the data we have, not re-arrange it the way we like it. That being said, this will remove all sub-sequent entries from the array that are duplicates.
$array = Array(
Array(
'name' => 'Test 3',
'slug' => 'test-3'
),
Array(
'name' => 'Foo',
'slug' => 'Bar'
),
Array(
'name' => 'Foo',
'slug' => 'Bar'
),
Array(
'name' => 'Test 1',
'slug' => 'test-1'
),
Array(
'name' => 'Test 2',
'slug' => 'test-2'
),
Array(
'name' => 'Test 3',
'slug' => 'test-3'
),
);
var_dump($array);
for ($e = 0; $e < count($array); $e++)
{
$duplicate = null;
for ($ee = $e+1; $ee < count($array); $ee++)
{
if (strcmp($array[$ee]['name'],$array[$e]['name']) === 0)
{
$duplicate = $ee;
break;
}
}
if (!is_null($duplicate))
array_splice($array,$duplicate,1);
}
var_dump($array);
Which will look like this:
array(6) {
[0]=>
array(2) {
["name"]=>
string(6) "Test 3"
["slug"]=>
string(6) "test-3"
}
[1]=>
array(2) {
["name"]=>
string(3) "Foo"
["slug"]=>
string(3) "Bar"
}
[2]=>
array(2) {
["name"]=>
string(3) "Foo"
["slug"]=>
string(3) "Bar"
}
[3]=>
array(2) {
["name"]=>
string(6) "Test 1"
["slug"]=>
string(6) "test-1"
}
[4]=>
array(2) {
["name"]=>
string(6) "Test 2"
["slug"]=>
string(6) "test-2"
}
[5]=>
array(2) {
["name"]=>
string(6) "Test 3"
["slug"]=>
string(6) "test-3"
}
}
array(4) {
[0]=>
array(2) {
["name"]=>
string(6) "Test 3"
["slug"]=>
string(6) "test-3"
}
[1]=>
array(2) {
["name"]=>
string(3) "Foo"
["slug"]=>
string(3) "Bar"
}
[2]=>
array(2) {
["name"]=>
string(6) "Test 1"
["slug"]=>
string(6) "test-1"
}
[3]=>
array(2) {
["name"]=>
string(6) "Test 2"
["slug"]=>
string(6) "test-2"
}
}
$array = array(
0 => array(
"name"=> "Foo",
"slug"=> "Bar"
),
1 => array(
"name"=> "Foo",
"slug"=> "Bar"
),
2 => array(
"name"=> "Test 1",
"slug"=> "test-1"
),
3 => array(
"name"=> "Test 2",
"slug"=> "test-2"
),
4 => array(
"name"=> "Test 3",
"slug"=> "test-3"
)
);
function array_unique_by_key (&$array, $key) {
$tmp = array();
$result = array();
foreach ($array as $value) {
if (!in_array($value[$key], $tmp)) {
array_push($tmp, $value[$key]);
array_push($result, $value);
}
}
return $array = $result;
}
array_unique_by_key($array, "name");
Just looking at your particular case, I would recommend using a hash table instead of a 2-dimensional array. If you use your "name" as the key in the hash, each entry would be unique.
Is there a specific need for the multidimensional array?
function multi_array_unique_by_value($array, $colon = '')
{
$ret_array = array();
$has_array = array();
foreach($array as $item)
{
$item_array = (array)$item;
if(!in_array($item_array[$colon], $has_array))
{
array_push($ret_array, $item);
array_push($has_array, $item_array[$colon]);
}
}
return $ret_array;
}
You can give your array here and give a colon name for making unique.
On this code, you have multidimensonal array, we foreach that array, which column index for us, we pushing that column values. And when same value, its not adding return array.
So this solution for array_unique for 1 coloumn.
Much simpler solution for your multidimensional array.
$unique = array_map('unserialize', array_unique(array_map('serialize', $array)));
echo "<pre>";
print_r($unique);

Categories