I have two multidimensional arrays that consist of arrays and objects.
$new = [
'a' => 'b',
'c' => (object)[
'd' => [1 => 11, 2 => 12],
'f' => 'Hello',
],
];
$old = [
'a' => 'b',
'c' => (object) [
'd' => [1 => 11, 2 => 22],
'f' => 'Goodbye',
],
];
I'm trying to find differences between these two arrays by using below function, but the result seems wrong when two objects are compared together. How can I change this function to get correct output?
function compare($array1, $array2)
{
$result = array();
foreach ($array1 as $key => $value) {
if (is_array($value)) {
if (array_key_exists($key, $array2)) {
$recursiveArrayDiff = compare($value, $array2[$key]);
if (count($recursiveArrayDiff)) {
$result[$key] = $recursiveArrayDiff;
}
continue;
}
else {
$result[$key] = $value;
continue;
}
}
if (is_object($value)) {
if (isset($key, $array2) && is_object($array2[$key])) {
$props = array_keys(get_object_vars($value));
foreach ($props as $prop) {
if (isset($array2[$key]->{$prop})) {
if (is_object($value->{$prop}) && is_object($array2[$key]->{$prop})) {
$temp = compare($value->{$prop}, $array2[$key]->{$prop});
if (count($temp)) {
$result[$key] = array($prop => $temp);
}
continue;
} elseif (is_array($value->{$prop}) && is_array($array2[$key]->{$prop})) {
$temp = compare($value->{$prop}, $array2[$key]->{$prop});
if (count($temp)) {
$result[$key] = array($prop => $temp);
}
continue;
} else {
if ($value->{$prop} != $array2[$key]->{$prop}) {
$result[$key] = array($prop => $value->{$prop});
}
}
} else {
$result[$key] = array($prop => $value->{$prop});
}
}
}
}
if ($value != $array2[$key]) {
$result[$key] = $value;
}
}
return $result;
}
The correct and wrong outputs are as follows:
//correct output
Array
(
[c] => stdClass Object
(
[d] => Array
(
[2] => 12
)
[f] => Hello
)
)
//wrong output
Array
(
[c] => stdClass Object
(
[d] => Array
(
[1] => 11
[2] => 12
)
[f] => Hello
)
)
I'm trying to get an xml file from an associative array having array keys encapsuled into '<' and '>'
I've tried to use a recursive function but it works correctly only on the first level:
Please remember my final goal is to create an xml, so any appropriate suggest is welcome
this is what I've done so far:
$arr =
array('<Lev0_0>' => 0,
'<Lev0_1>' => 1,
'<Lev0_2>' => array (
'<Lev1_0>' => 2,
'<Lev1_1>' => 3
)
);
print_r(RepairKeysMultidimensional($arr));
function RepairKeysMultidimensional(array $array){
$Keys = array();
foreach($array as $Key => $Value){
$NewKey = str_replace(array('<','>'),'',$Key);
$array[$NewKey] = $Value;
unset($array[$Key]);
if(is_array($Value)){
RepairKeysMultidimensional($Value);
}
}
return $array;
}
the output is:
Array (
[Lev0_0] => 0
[Lev0_1] => 1
[Lev0_2] => Array (
[] => 2
[] => 3
)
)
If that's the structure and you never expect < or > as part of the values, you don't need to loop over it just json_encode it, strip out the chars and the json_decode it back into an array.
<?php
$arr = array(
'<Lev0_0>' => 0,
'<Lev0_1>' => 1,
'<Lev0_2>' => array (
'<Lev1_0>' => 2,
'<Lev1_1>' => 3
)
);
$arr = json_decode(str_replace(array('<','>'), '', json_encode($arr)), true);
print_r($arr);
https://3v4l.org/2d7Hq
Result:
Array
(
[Lev0_0] => 0
[Lev0_1] => 1
[Lev0_2] => Array
(
[Lev1_0] => 2
[Lev1_1] => 3
)
)
Try to add affectation in your if statement:
function RepairKeysMultidimensional(array $array){
$Keys = array();
foreach($array as $Key => $Value){
$NewKey = str_replace(array('<','>'),'',$Key);
$array[$NewKey] = $Value;
unset($array[$Key]);
if (is_array($Value)) {
$array[$NewKey] = RepairKeysMultidimensional($Value);
}
}
return $array;
}
you are not affecting the result of the second call to the outer array!
Try this :
<?php
$arr =
array('<Lev0_0>' => 0,
'<Lev0_1>' => 1,
'<Lev0_2>' => array (
'<Lev1_0>' => 2,
'<Lev1_1>' => 3
)
);
echo str_replace(array('<','>'),'','<Lev0>');
echo '<br/><br/>';
print_r(RepairKeysMultidimensional($arr));
function RepairKeysMultidimensional(array $array){
$Keys = array();
foreach($array as $Key => $Value){
$NewKey = str_replace(array('<','>'),'',$Key);
unset($array[$Key]);
if(is_array($Value)){
$array[$NewKey] = RepairKeysMultidimensional($Value);
}else{
$array[$NewKey] = $Value;
}
}
return $array;
}
The output of this is :
Array (
[Lev0_0] => 0
[Lev0_1] => 1
[Lev0_2] => Array (
[Lev1_0] => 2
[Lev1_1] => 3 ) )
After implementing database queries, I am getting the multi-dimensional array below.
Two Dimensional Array
Array
(
[0] => Array
(
[t1] => test1
)
[1] => Array
(
[t2] => test2
)
[2] => Array
(
[t3] => test3
)
[3] => Array
(
[t4] => test4
)
[4] => Array
(
[t5] => test5
)
)
but I want to convert it to a single dimensional array, like the format below:
One Dimensional Array
Array (
t1 => test1
t2 => test2
t3 => test3
t4 => test4
t5 => test5
)
How can I do this?
I think you can use array_reduce() function.
For example:
$multi= array(0 => array('t1' => 'test1'),1 => array('t2' => 'test2'),2 => array('t3' => 'test3'),3 => array('t4' => 'test4'));
$single= array_reduce($multi, 'array_merge', array());
print_r($single); //Outputs the reduced aray
You can use as follows :
$newArray = array();
foreach($arrayData as $key => $value) {
foreach($value as $key2 => $value2) {
$newArray[$key2] = $value2;
}
}
Where $arrayData is your DB data array and $newArray will be the result.
Assuming that source array is array of arrays and it has no the same keys:
<?php
$src = [
['t1'=>'test1'],
['t2'=>'test2'],
['t3'=>'test3'],
['t4'=>'test4'],
['t5'=>'test5'],
];
$result = call_user_func_array('array_merge', $src);
result via var_dump():
array(5) {
["t1"]=>
string(5) "test1"
["t2"]=>
string(5) "test2"
["t3"]=>
string(5) "test3"
["t4"]=>
string(5) "test4"
["t5"]=>
string(5) "test5"
}
You can use array_reduce() to change values of array. In callback get key of item using key() and select first item using reset().
$newArr = array_reduce($oldArr, function($carry, $item){
$carry[key($item)] = reset($item);
return $carry;
});
Check result in demo
Try this function,
function custom_function($input_array)
{
$output_array = array();
for ($i = 0; $i < count($input_array); $i++) {
for ($j = 0; $j < count($input_array[$i]); $j++) {
$output_array[key($input_array[$i])] = $input_array[$i][key($input_array[$i])];
}
}
return $output_array;
}
$arr = custom_function($arr);
print_r($arr);
Give it a try, it will work.
You can use this
<?php
$temp = array(array('t1' => 'test1'), array('t2' => 'test2'), array('t3' => 'test3'), array('t4' => 'test4'), array('t5' => 'test5'));
$result_array = array();
foreach ($temp as $val) {
foreach ($val as $key => $inner_val) {
$result_array[$key] = $inner_val;
}
}
print_r($result_array);
?>
// Multidimensional array
$arrdata = Array(
'0' => Array(
't1' => 'test1'
) ,
'1' => Array(
't2' => 'test2'
) ,
'2' => Array(
't3' => 'test3'
)
);
// Convert to a single array
$data = array();
foreach($arrdata as $key => $value) {
foreach($value as $key1 => $value1) {
$data[$key1] = $value1;
}
}
echo $data;
Try array map function.
$singleDimensionArray = array_map('current',$multiDimensionArray);
You can use this if you don't care about keeping the correct array keys
function flattenA(array $array) {
$return = array();
array_walk_recursive($array, function($a) use (&$return) { $return[] = $a; });
return $return;
}
print_r(flattenA($arr));
// Output
Array
(
[0] => test1
[1] => test2
[2] => test3
[3] => test4
[4] => test5
)
Otherwise
function flattenB(array $array) {
$return = array();
array_walk_recursive($array, function($v,$k) use (&$return) { $return[$k] = $v; });
return $return;
}
print_r(flattenB($arr));
// Output
Array
(
[t1] => test1
[t2] => test2
[t3] => test3
[t4] => test4
[t5] => test5
)
Check both on Sandbox
From answer on similar question
For your specific case, I would use array_reduce where I set the initial value with an empty array
array_reduce($arr, function($last, $row) {
return $last + $row;
}, array());
AFTER PHP 7.4
array_reduce($arr, fn ($last, $row) => $last + $row, []);
Result :
[
't1' => 'test1',
't2' => 'test2',
't3' => 'test3',
't4' => 'test4',
't5' => 'test5'
]
Hey #Karan Adhikari Simple like below one:
<?php
$arr1 = array(array("t1" => "test1"), array("t2" => "test2"), array("t3" => "test3"), array("t4" => "test4"), array("t5" => "test5"));
echo "<pre>";
print_r($arr1);//before
$arr2 = array();
foreach($arr1 as $val){
$arr2 = array_merge($arr2, $val);
}
echo "<pre>";
print_r($arr2); // after you get your answer
Please try this function:
function array_merging($multi_array) {
if (is_array($multi_array)) {
$new_arr = array();
foreach ($multi_array as $key => $value) {
if (is_array($value)) {
$new_arr = array_merge($new_arr, array_merging($value));
}
else {
$new_arr[$key] = $value;
}
}
return $new_arr;
}
else {
return false;
}
}
Use this function:
$your_multi_arr = array(array(array('t1'=>'test1'),array('t2'=>'test2'),array('t3'=>'test3'),array('t4'=>'test4')));
$arr1 = array_merging($your_multi_arr);
echo "<pre>";
print_r($arr1);
Hope, this may be useful for you.
You can try traversing the array using PHP while list and each. I took sample code from PHP website the second example you can check it here
$arr = [['t1' => 'test1'],['t2' => 'test2'],['t3' => 'test3'],['t4' => 'test4'],['t5' => 'test5']];
$output = [];
while (list($key, $val) = each($arr)) {
while (list($k, $v) = each($val)) {
$output[$k] = $v;
}
}
print_r($output);
Output created is
Array
(
[t1] => test1
[t2] => test2
[t3] => test3
[t4] => test4
[t5] => test5
)
You can test it on your own in this Sandbox example.
This will do the trick
$array = array_column($array, 't1');
Note: This function array_column introduced in PHP 5.5 so it won't work in earlier versions.
traverse the array and save the key value, Live Demo here.
<?php
$array = array(array('t1' => 'test1'), array('t2' => 'test2'), array('t3' => 'test3'), array('t4' => 'test4'), array('t5' => 'test5'));
$result = [];
array_walk($array, function($value) use(&$result){
foreach($value as $k => $v)
{
$result[$k] = $v;
}
});
var_dump($result);
`$result = "Query"; $key_value = array();`
foreach ($result as $key => $value) {
$key_value[$key['']] = $value[''];
}
//for checking //echo "<pre>" ; print_r($key_value) ; exit;
return $key_value;
pls fill $key['name given in sql query for field'] and $value['name given in sql query for field'] (both are same)
this works for me
$result = [];
foreach($excelEmails as $arr)
{
foreach ($arr as $item){
$result = array_merge($result , $item);
}
}
dd($result);
i would recomment my way to convert all double-dimensional array to single-dimensional array.
<?php
$single_Array = array();
//example array
$array = array(
array('t1' => 'test1'),
array('t2' => 'test2'),
array('t3' => 'test3'),
array('t4' => 'test4'),
array('t5' => 'test5'));
$size = sizeof($array);
//loop to fill the new single-dimensional array
for($count = 0; $count<sizeof($array);$count++)
{
//take the key of multi-dim array
$second_cell = key($array[$count]);
//set the value into the new array
$single_array[$count] = $array[$count][$second_cell];
}
//see the results
var_dump($single_array);
?>
with this script we can take keys and values to create new single-dimensional array.I hope that i was helpfull to you.
you can see the example here: Array Convert Demo
I have the following array:
Array
(
[0] => Array
(
[dest_in_id] => 1
[dest_user_id] => 37251
[dest_inv_user_id] => 37247
[dest_timestamp] => 1387168510
[dest_destination_id] => 64
)
[1] => Array
(
[gi_in_id] => 3
[gi_user_id] => 37251
[gi_inv_user_id] => 14564
[gi_timestamp] => 1345220045
[gi_group_id] => 2
)
[2] => Array
(
[dest_in_id] => 2
[dest_user_id] => 37251
[dest_inv_user_id] => 37257
[dest_timestamp] => 1387168510
[dest_destination_id] => 64
)
[3] => Array
(
[gi_in_id] => 3
[gi_user_id] => 37251
[gi_inv_user_id] => 14564
[gi_timestamp] => 1345220045
[gi_group_id] => 2
)
)
Need to review the difference in Timestamp each array and if it <= day (86400), then create an array type:
Array
(
[1387168510] => Array
(
[0] => Array
(
[dest_in_id] => 1
[dest_user_id] => 37251
[dest_inv_user_id] => 37247
[dest_timestamp] => 1387168510
[dest_destination_id] => 64
)
[1] => Array
(
[dest_in_id] => 2
[dest_user_id] => 37251
[dest_inv_user_id] => 37257
[dest_timestamp] => 1387168510
[dest_destination_id] => 64
)
)
[1345220045] => Array
(
[0] => Array
(
[gi_in_id] => 3
[gi_user_id] => 37251
[gi_inv_user_id] => 14564
[gi_timestamp] => 1345220045
[gi_group_id] => 2
)
[1] => Array
(
[gi_in_id] => 3
[gi_user_id] => 37251
[gi_inv_user_id] => 14564
[gi_timestamp] => 1345220045
[gi_group_id] => 2
)
)
)
Important note! Keys may be different!
At once appealed to the function usort. Wanted to do something like this:
usort($aInvitesRows, function($a, $b) {
$akey = array_keys($a);
$bkey = array_keys($b);
if (($b[preg_grep("/(.*?)_timestamp/", $bkey)[3]] - $a[preg_grep("/(.*?)_timestamp/", $akey)[3]]) <= 86400) {
return $b[preg_grep("/(.*?)_timestamp/", $bkey)[3]] = array($a, $b);
}
});
Success of this venture was not crowned :(
At this stage, using usort could only sort by Timestamp (*), what do you do - do not know the, address for the help!
*
usort($aInvitesRows, function($a, $b) {
$akey = array_keys($a);
$bkey = array_keys($b);
return strcmp($b[preg_grep("/(.*?)_timestamp/", $bkey)[3]], $a[preg_grep("/(.*?)_timestamp/", $akey)[3]]);
});
function msort($array, $key, $sort_flags = SORT_REGULAR) {
if (is_array($array) && count($array) > 0) {
if (!empty($key)) {
$mapping = array();
foreach ($array as $k => $v) {
$sort_key = '';
if (!is_array($key)) {
$sort_key = $v[$key];
} else {
// #TODO This should be fixed, now it will be sorted as string
foreach ($key as $key_key) {
$sort_key .= $v[$key_key];
}
$sort_flags = SORT_STRING;
}
$mapping[$k] = $sort_key;
}
asort($mapping, $sort_flags);
$sorted = array();
foreach ($mapping as $k => $v) {
$sorted[] = $array[$k];
}
return $sorted;
}
}
return $array;
}
$arr = $aInvitesRows;
$result = array();
$item = array_shift($arr);
$akeys = array_keys($item);
$dt = new \DateTime();
$dt->setTimestamp($item[preg_grep("/(.*?)_timestamp/", $akeys)[3]]);
$dt->setTime(0, 0, 0);
$result[$dt->getTimestamp()] = array($item);
foreach ($arr as $item) {
$akeys = array_keys($item);
$f = false;
foreach ($result as $day => $items) {
$diff = ($item[preg_grep("/(.*?)_timestamp/", $akeys)[3]]) - $day;
if ($diff < 86400 && $diff > 0) {
$result[$day][] = $item;
$f = true;
break 1;
}
}
if (!$f) {
$dt = new \DateTime();
$dt->setTimestamp($item[preg_grep("/(.*?)_timestamp/", $akeys)[3]]);
$dt->setTime(0, 0, 0);
$result[$dt->getTimestamp()] = array($item);
}
}
I have this two arrays:
$arr1['product_detail'] = array(
"26" => array("Blue", "Green"),
"28" => array("S")
);
$arr2['variation'] = array(
"pupc" => array("123456", "654321"),
"pprice" => array(1, 2),
"pqty" => array(10, 11)
);
I need to build a new array containing values based on position, less said:
$arr3 = array(
array("Blue", "S", "123456", 1, 10),
array("Green", "S", "654321", 2, 11)
);
If you notice I mix all the position of both original arrays. I think in something like:
foreach ($arr2 as $key => $value) {
foreach ($value as $key1 => $value1) {
foreach ($value1 as $key2 => $value2) {
foreach ($arr1 as $key3 => $value3) {
echo $key3;
}
}
}
}
But it's very ugly and I think is better ways to do this, any help?
It is good idea to use a function
function array_addition($main_array, $new_array) {
foreach ($new_array as $aItem) {
for ($i=0;$i<=1;$i++) {
$main_array[$i][] = current($aItem) ? current($aItem) : reset($aItem);
next($aItem);
}
}
return $main_array;
}
$arr3 = array();
$arr3 = array_addition($arr3, $arr1['product_detail']);
$arr3 = array_addition($arr3, $arr2['variation']);
$arr1['product_detail'] = array(
"26" => array("Blue", "Green"),
"28" => array("S")
);
$arr2['variation'] = array(
"pupc" => array("123456", "654321"),
"pprice" => array(1, 2),
"pqty" => array(10, 11)
);
function convert_array_index_name_to_number($arr)
{
$temp_ar = array();
foreach($arr as $key=>$val)
{
if(is_array($val))
{
$val = convert_array_index_name_to_number($val);
}
$temp_ar[] = $val;
}
return $temp_ar;
}
$arr1 = convert_array_index_name_to_number($arr1);
$arr2 = convert_array_index_name_to_number($arr2);
$arr3 = array();
for($i=0; $i<$count_of_variations; $i++)
{
$temp_arr = array();
$temp_arr[] = $arr1[0][0][$i];
$temp_arr[] = $arr1[0][1][0];
foreach($arr2[0] as $key => $value)
{
$temp_arr[] = $value[$i];
}
$arr3[] = $temp_arr;
}
Result
Array
(
[0] => Array
(
[0] => Blue
[1] => S
[2] => 123456
[3] => 1
[4] => 10
)
[1] => Array
(
[0] => Green
[1] => S
[2] => 654321
[3] => 2
[4] => 11
)
)