Multidimensional array difference - php

I need find difference between multidimensional arrays
I have arrays like this :
$arr1 = array(
'test1' => array(
'XXX' => array(
'w1' => array('id' => '5'),
'w2' => array('id' => '2'),
'w3' => array('id' => 'g'),
),
'YYY' => array(
'w1' => array('id' => '4'),
'w2' => array('id' => '1')
),
'ZZZ' => array(
'w1' => array('id' => '3'),
'w2' => array('id' => '9')
),
'QQQ' => array(
'w1' => array('id' => '3'),
'w2' => array('id' => '9')
),
),
'test2' => array(
'XXX' => array(
'w1' => array('id' => '8'),
'w2' => array('id' => '3')
),
'YYY' => array(
'w1' => array('id' => '15'),
'w2' => array('id' => '1')
),
'ZZZ' => array(
'w1' => array('id' => '5'),
'w2' => array('id' => '2')
),
),
);
$arr2 = array(
'test1' => array(
'XXX' => array(
'w1' => array('id' => '5'),
'w2' => array('id' => '2'),
'w3' => array('id' => 'g'),
'w4' => array('id' => 'x'),
),
'YYY' => array(
'w1' => array('id' => '4'),
'w2' => array('id' => '1')
),
'ZZZ' => array(
'w1' => array('id' => '3'),
'w2' => array('id' => '9')
),
),
);
And I need to remove duplicates but I need compare first level key, second level key and last level key,value pairs so my results should be like that
array(
'test1' => array(
'XXX' => array(
'w4' => array('id' => 'x'),
),
)
I try use
function check_key($a,$b) {
if ($a===$b)
{
return 0;
}
return ($a>$b)?1:-1;
}
function check_value($a,$b) {
if ($a===$b)
{
return 0;
}
return ($a>$b)?1:-1;
}
$merged_arr = array_udiff_uassoc($arr2,$arr1,"check_key","check_value");
But this function don't compare last level key-value pair in last level .

Try with this function.I think It will be helpful to you.
$result[] = array_diff_key($arr1, $arr2);
print_r($result);

Related

How to control the depth of php infinite pole classification

Here is my array:
$list = array(
array('id' => 3, 'name' => 'Phones', 'parent_id' => 0,),
array('id' => 256, 'name' => 'Accessories', 'parent_id' => 0,),
array('id' => 308, 'name' => 'Appliances', 'parent_id' => 0,),
array('id' => 1057, 'name' => 'Smart', 'parent_id' => 0,),
array('id' => 1065, 'name' => 'Smart Phones', 'parent_id' => 3,),
array('id' => 1066, 'name' => 'Feature Phones', 'parent_id' => 3,),
array('id' => 1069, 'name' => 'Samsung', 'parent_id' => 1065,),
array('id' => 1070, 'name' => 'Apple', 'parent_id' => 1065,),
array('id' => 1072, 'name' => 'Apple', 'parent_id' => 1066,),
array('id' => 1075, 'name' => 'Tablets', 'parent_id' => 0,),
array('id' => 1076, 'name' => 'Samsung', 'parent_id' => 1066,),
array('id' => 1077, 'name' => 'All Brands', 'parent_id' => 1075,),
array('id' => 1078, 'name' => 'Samsung', 'parent_id' => 1077,),
array('id' => 1079, 'name' => 'Protector', 'parent_id' => 256,),
array('id' => 1080, 'name' => 'Power', 'parent_id' => 256,),
array('id' => 1081, 'name' => 'Cable', 'parent_id' => 256,),
array('id' => 1082, 'name' => 'Memory', 'parent_id' => 256,),
);
This is the code I categorized:
function quote_make_tree($list,$deep=1, $root = 0)
{
$tree = $packData = [];
foreach ($list as $row) {
$packData[$row['id']] = $row;
}
foreach ($packData as $key => $val) {
if ($val['parent_id'] == $root) {
$tree[] = &$packData[$key];
} else {
$packData[$val['parent_id']]['children'][] = &$packData[$key];
}
}
return $tree;
}
I want to add a deep parameter $deep to quote_make_tree to control the depth of classification.
The result I want:
If $deep = 1 Get only data with parent_id = 0:
$one = array(
0 => array('id' => 3, 'name' => 'Phones', 'parent_id' => 0,),
1 => array('id' => 256, 'name' => 'Accessories', 'parent_id' => 0,),
2 => array('id' => 308, 'name' => 'Appliances', 'parent_id' => 0,),
3 => array('id' => 1057, 'name' => 'Smart', 'parent_id' => 0,),
4 => array('id' => 1075, 'name' => 'Tablets', 'parent_id' => 0,),
);
If $deep = 2,Get level 2 classification below level 1 classification,if $deep=3,Get all 1,2,3 classifications
I have tried get all the data first, then delete the data according to $deep.here is demo,thanks folks
This might be easier to solve using a recursive method. This allows you to check the depth and if you want more details then it will call itself to add in more layers. Each time calling itself you just take one off the depth...
function quote_make_tree($list, $deep=1, $root = 0) {
$output = [];
foreach ( $list as $listItem ) {
if ( $listItem['parent_id'] == $root ) {
if ( $deep > 1 ) {
$listItem['children'] = quote_make_tree($list, $deep-1, $listItem['id']);
}
$output[] = $listItem;
}
}
return $output;
}

Check if key exist in array if so, count it and create a new array php

From my SQL query, I will get the following array as a result. This is the last result I can get from SQL.I cant change any SQL because of some constraint.
I need to check if the same id exists or not and if it does need to count them and remove one of the duplicate array having the same id.
Sample array is
$array = array(
0 => array(
'id' => '17',
'status' => 1,
),
1 => array(
'id' => '18',
'status' => 1,
),
2 => array(
'id' => '21',
'status' => 1,
),
3 => array(
'id' => '5',
'status' => 2,
),
4 => array(
'id' => '18',
'status' => 1,
),
5 => array(
'id' => '22',
'status' => 5,
),
6 => array(
'id' => '6',
'status' => 1,
),
);
I need to check if they have a duplicate id or not, if yes need to count them and remove one of the duplicates.We need to preserve the array structure.
End Results should be
array(
0 => array(
'id' => '17',
'status' => 1,
'count'=1,
),
1 => array(
'id' => '18',
'status' => 1,
'count'=2,
),
2 => array(
'id' => '21',
'status' => 1,
'count'=1,
),
3 => array(
'id' => '5',
'status' => 2,
'count'=1,
),
4 => array(
'id' => '22',
'status' => 5,
'count'=1,
),
5 => array(
'id' => '6',
'status' => 1,
'count'==>1,
),
)
You can Check it by this way but duplicate entry still in the array.
$ids = array();
foreach ($array as $key => $value)
{
$ids[] = $value['id'];
$count = array_count_values($ids);
}
for($i = 0; $i < count($array);$i++)
{
$array[$i]['count'] = $count[$array[$i]['id']];
}
You can do this with the array_unique function.
Use it like so:
$a=array("a"=>"red","b"=>"green","c"=>"red");
print_r(array_unique($a));
Which outputs:
Array ( [a] => red [b] => green )

Loop into an array of array with PHP

I have this array,
$bookings[] = array(
'booking_id' => '1',
'client_name' => 'John',
'client_firstname' => 'Peter',
'days' => array(
array(
'day_id' => '2016-11-23',
'room_id' => '2'
),
array(
'day_id' => '2016-11-24',
'room_id' => '2'
),
array(
'day_id' => '2016-11-25',
'room_id' => '4'
)
)
)
I'm looking for looping into the days array with PHP.
How is it possible please ?
Thanks for your help.
demo
<?php
$bookings[] = array(
'booking_id' => '1',
'client_name' => 'John',
'client_firstname' => 'Peter',
'days' => array(
array(
'day_id' => '2016-11-23',
'room_id' => '2'
),
array(
'day_id' => '2016-11-24',
'room_id' => '2'
),
array(
'day_id' => '2016-11-25',
'room_id' => '4'
)
)
);
foreach($bookings as $booking)
{
foreach($booking['days'] as $day)
{
echo $day['day_id'];
echo "\n";
}
}

PHP: Help with Sorting Array

How can I sort an associative array by a weight AND type?
Input
array(
'a' => array( 'type' => 't1', 'weight' => 1, 'text' => 'text1' ),
'b' => array( 'type' => 't1', 'weight' => 3, 'text' => 'text2' ),
'c' => array( 'type' => 't2', 'weight' => 5, 'text' => 'text3' ),
'd' => array( 'type' => 't1', 'weight' => 2, 'text' => 'text4' ),
'e' => array( 'type' => 't2', 'weight' => 4, 'text' => 'text5' ),
'f' => array( 'type' => 't2', 'weight' => 4, 'text' => 'text6' )
);
Desired Output
array(
'a' => array( 'type' => 't1', 'weight' => 1, 'text' => 'text1' ),
'd' => array( 'type' => 't1', 'weight' => 2, 'text' => 'text4' ),
'b' => array( 'type' => 't1', 'weight' => 3, 'text' => 'text2' ),
'e' => array( 'type' => 't2', 'weight' => 1, 'text' => 'text5' ),
'f' => array( 'type' => 't2', 'weight' => 1, 'text' => 'text6' ),
'c' => array( 'type' => 't2', 'weight' => 5, 'text' => 'text3' )
);
Type "t2" must appear at end of array, all other types at start.
Weight must be sorted after type.
I am using uasort with a custom compare function, but am struggling. Here is what I have, but it doesn't work:
function my_comparer($a, $b) {
return ( $a['type'] !== 't2' && $b['type'] === 't2' )
? -1
: $a['weight'] - $b['weight'];
}
Your function doesn't take account of ($a['type']=='t2')
function my_comparer($a, $b) {
if ( ($a['type']==='t2') && ($b['type']!=='t2')) return -1;
if ( ($b['type']==='t2') && ($a['type']!=='t2')) return 1;
return ($a['weight'] - $b['weight']);
}
Try this:
function my_comparer($a, $b) {
if( $a['type'] == $b['type'] ){
return $a['weight'] - $b['weight'];
}else{
if( $a['type'] > $b['type'] ) return 1;
else return -1;
}
}
(warning, this is untested)
Simpler way would be array_multisort
$data = array(
'a' => array( 'type' => 't1', 'weight' => 1, 'text' => 'text1' ),
'b' => array( 'type' => 't1', 'weight' => 3, 'text' => 'text2' ),
'c' => array( 'type' => 't2', 'weight' => 5, 'text' => 'text3' ),
'd' => array( 'type' => 't1', 'weight' => 2, 'text' => 'text4' ),
'e' => array( 'type' => 't2', 'weight' => 4, 'text' => 'text5' ),
'f' => array( 'type' => 't2', 'weight' => 4, 'text' => 'text6' )
);
// Obtain a list of columns
foreach ($data as $key => $row) {
$type[$key] = $row['type'];
$weight[$key] = $row['weight'];
}
array_multisort($type, SORT_ASC, $weight, SORT_ASC, $data);
Plus this works if you add any number of types you want sorted in the same way.
Helper function:
function arrayColumnSort(&$array, $directions) {
// collect columns
$columnNames = array_keys($directions);
$columns = array();
foreach ($array as $row) {
foreach ($columnNames as $columnName) {
if (!isset($columns[$columnName])) {
$columns[$columnName] = array();
}
$columns[$columnName][] = isset($row[$columnName]) ? $row[$columnName] : null;
}
}
// build array_multisort params
$params = array();
foreach ($directions as $columnName => $direction) {
$params = array_merge(
$params,
array($columns[$columnName]),
is_array($direction) ? $direction : array($direction)
);
}
$params[] =& $array;
// sort
call_user_func_array('array_multisort', $params);
}
Call:
arrayColumnSort($data, array(
'type' => SORT_ASC,
'weight' => SORT_ASC,
));

Fastest way to format SQL results in PHP

What's the fastest (best performing) way in PHP to transform a (My)SQL result like:
array(
array('user_name' => 'john', 'tag_id' => 1, 'tag_name' => 'foo'),
array('user_name' => 'john', 'tag_id' => 2, 'tag_name' => 'bar'),
array('user_name' => 'rick', 'tag_id' => 3, 'tag_name' => 'foobar'),
array('user_name' => 'rick', 'tag_id' => 2, 'tag_name' => 'bar')
);
Into the easier to use:
array(
array('name' => 'john', 'tags' => array(
array('id' => 1, 'name' => 'foo'),
array('id' => 2, 'name' => 'bar')
),
array('name' => 'rick', 'tags' => array(
array('id' => 3, 'name' => 'foobar'),
array('id' => 2, 'name' => 'bar')
)
);
Or is there a library that does this already, without the added inflexibility and performance hit of full ORM?
Thanks
Try this:
$data = array(
array('user_name' => 'john', 'tag_id' => 1, 'tag_name' => 'foo'),
array('user_name' => 'john', 'tag_id' => 2, 'tag_name' => 'bar'),
array('user_name' => 'rick', 'tag_id' => 3, 'tag_name' => 'foobar'),
array('user_name' => 'rick', 'tag_id' => 2, 'tag_name' => 'bar')
);
$final = array();
foreach ($data as $item) {
if (!isset($final[$item['user_name']])) {
$final[$item['user_name']] = array(
'name' => $item['user_name'],
'tags' => array()
);
}
$final[$item['user_name']]['tags'][] = array(
'id' => $item['tag_id'],
'name' => $item['tag_name']
);
}
$final = array_values($final);
ezSQL at http://www.woyano.com/jv/ezsql should do what you want. I've taken over a project that uses it and it appear quite nicely put together. Myself I prefer to be somewhat closer to the metal, but if you wish to abstract away then it appears pretty solid in my experience.

Categories