Merging two arrays with weight of index in both - php

I have two array like this and want to merge like
Take 1st index Array 1 check
if it is present in Array 2
Insert in Array 3
add weight of Array 1 and Array 2
else if not present
take 1st index of Array 2
Take 1st index of Array 2 and check
if it is present in Array 1
Insert in Array 3
add weight of Array 1 and Array 2
else if not present
take 2nd index of Array 1
Take 2nd index of Array 1 and check
if it is present in Array 2
Insert in Array 3
add weight of Array 1 and Array 2
else if not present
take 1st index of Array 2
Take 1st index of Array 2 and check
Note above logic is for given example
For Example
Array 1
(
[144] => Array
(
[weight] => 2
)
[145] => Array
(
[weight] => 1
)
[177] => Array
(
[weight] => 1
)
)
Array 2
(
[93] => Array
(
[weight] => 4
)
[133] => Array
(
[weight] => 4
)
[144] => Array
(
[weight] => 4
)
[145] => Array
(
[weight] => 4
)
[141] => Array
(
[weight] => 1
)
)
I want result as
Array 3
(
[144] => Array
(
[weight] => 6
)
[145] => Array
(
[weight] => 5
)
[93] => Array
(
[weight] => 4
)
[133] => Array
(
[weight] => 4
)
[177] => Array
(
[weight] => 1
)
[141] => Array
(
[weight] => 1
)
)
Thanks in Advance

$out = array();
foreach ($arr1 as $key => $val) {
if (isset($out[$key]['weight'])) {
$out[$key]['weight'] += $val['weight'];
} else {
$out[$key]['weight'] = $val['weight'];
}
}
foreach ($arr2 as $key => $val) {
if (isset($out[$key]['weight'])) {
$out[$key]['weight'] += $val['weight'];
} else {
$out[$key]['weight'] = $val['weight'];
}
}
print_r($out);
Also, if you have an unknown number of arrays to work with you can do this:
$arrays = array (
$arr1,
$arr2,
$arr3
// ...
};
$out = array();
foreach ($arrays as $array) {
foreach ($array as $key => $val) {
if (isset($out[$key]['weight'])) {
$out[$key]['weight'] += $val['weight'];
} else {
$out[$key]['weight'] = $val['weight'];
}
}
}
print_r($out);

You seems to want second array first,
then append first array
maybe this is works
$a = ...; //first array
$b = ...; // second array
var_export($a);
var_export($b);
$rtn = $tmp = array();
foreach ($b as $idx=>$arr)
{
if (isset($a[$idx]))
{
$rtn[$idx]['weight'] = $arr['weight'] + $a[$idx]['weight'];
unset($a[$idx]);
}
else
{
$tmp[$idx]['weight'] = $arr['weight'];
}
}
$res = $rtn+$tmp+$a;
print_r($res);
result
array (
144 =>
array (
'weight' => 2,
),
145 =>
array (
'weight' => 1,
),
177 =>
array (
'weight' => 1,
),
)array (
93 =>
array (
'weight' => 4,
),
133 =>
array (
'weight' => 4,
),
144 =>
array (
'weight' => 4,
),
145 =>
array (
'weight' => 4,
),
141 =>
array (
'weight' => 1,
),
)Array
(
[144] => Array
(
[weight] => 6
)
[145] => Array
(
[weight] => 5
)
[93] => Array
(
[weight] => 4
)
[133] => Array
(
[weight] => 4
)
[141] => Array
(
[weight] => 1
)
[177] => Array
(
[weight] => 1
)
)

it's very simple task:
array_walk($a, function(&$value, $key, $b){
$value["weight"] += isset($b[$key]["weight"])?$b[$key]["weight"]:0;
}, $b);
$ret = $a+$b
given input:
$a = array(
1 => array(
"weight" => 1
),
2 => array(
"weight" => 5
)
);
$b = array(
1 => array(
"weight" => 2
),
3 => array(
"weight" => 4
)
);
would produce:
array(3) {
[1]=>
array(1) {
["weight"]=>
int(3)
}
[2]=>
array(1) {
["weight"]=>
int(5)
}
[3]=>
array(1) {
["weight"]=>
int(4)
}
}

Related

Group subsets of data in 3-level array by identifying column

I've this type of array in PHP:
Array(
[100] => Array(
[1] => Array (
[AVA_Date] => 2019-04-18
[ROO_Id] => 100
[RAT_Id] => 9
)
[2] => Array (
[AVA_Date] => 2019-04-20
[ROO_Id] => 100
[RAT_Id] => 10
)
[4] => Array (
[AVA_Date] => 2019-04-21
[ROO_Id] => 100
[RAT_Id] => 10
)
[7] => Array (
[AVA_Date] => 2019-04-22
[ROO_Id] => 100
[RAT_Id] => 9
)
)
)
I would like to merge items on ROO_Id and RAT_Id.
Then, for the AVA_Date, I need to list them under a new array in the current array.
So, the desired output is:
Array(
[100] => Array(
[0] => Array (
[AVA_Date] => Array (
[0] => 2019-04-18
[1] => 2019-04-22
)
[ROO_Id] => 100
[RAT_Id] => 9
)
[1] => Array (
[AVA_Date] => Array (
[0] => 2019-04-20
[1] => 2019-04-21
)
[ROO_Id] => 100
[RAT_Id] => 10
)
)
)
Here what I have tried:
$newArrOtherRooms = array_reduce($newArr, function($acc, $val) {
$room = array_search($val['ROO_Id'], array_column($acc, 'ROO_Id'));
$rate = array_search($val['RAT_Id'], array_column($acc, 'RAT_Id'));
if($rate == $room && $room > -1) {
array_push($acc[$room]['AVA_Date'], $val['AVA_Date']);
}
else {
$new_arr = $val;
$new_arr['AVA_Date'] = [$val['AVA_Date']];
array_push($acc, $new_arr);
}
return $acc;
},[]);
But it doesn't work like I want.
There are a couple of issues with your code. Firstly, you need to wrap the array_reduce with a foreach over the outer level of $newArr. Secondly, your call to array_search doesn't consider the fact that a ROO_Id or RAT_Id value might exist more than once in the array, as it only returns the first key at which it finds the value. To work around this, you can use array_keys to get an array of key values for each ROO_Id and RAT_Id value, and then take the intersection of those two arrays using array_intersect to see if both are present in the same element. If so, you update that element, otherwise you create a new one:
foreach ($newArr as $key => $array) {
$newArrOtherRooms[$key] = array_reduce($array, function($acc, $val) {
$room = array_keys(array_column($acc, 'ROO_Id'), $val['ROO_Id']);
$rate = array_keys(array_column($acc, 'RAT_Id'), $val['RAT_Id']);
$common = array_intersect($room, $rate);
if(!empty($common)) {
array_push($acc[current($common)]['AVA_Date'], $val['AVA_Date']);
}
else {
$new_arr = $val;
$new_arr['AVA_Date'] = [$val['AVA_Date']];
array_push($acc, $new_arr);
}
return $acc;
},[]);
}
print_r($newArrOtherRooms);
Output:
Array(
[100] => Array(
[0] => Array (
[AVA_Date] => Array (
[0] => 2019-04-18
[1] => 2019-04-22
)
[ROO_Id] => 100
[RAT_Id] => 9
)
[1] => Array (
[AVA_Date] => Array (
[0] => 2019-04-20
[1] => 2019-04-21
)
[ROO_Id] => 100
[RAT_Id] => 10
)
)
)
Demo on 3v4l.org
There is absolutely no reason to be making all of those iterated function calls.
Use a nested loop to iterate the subset of data for each room, group on the room "rate id", and push all "available date" values into a subarray in the respective group. When the subset of data is fully iterated, push its grouped data into the result array.
Code: (Demo)
$result = [];
foreach ($newArr as $rooId => $rows) {
$groups = [];
foreach ($rows as $row) {
if (!isset($groups[$row['RAT_Id']])) {
$row['AVA_Date'] = (array) $row['AVA_Date'];
$groups[$row['RAT_Id']] = $row;
} else {
$groups[$row['RAT_Id']]['AVA_Date'][] = $row['AVA_Date'];
}
}
$result[$rooId] = array_values($groups);
}
var_export($result);
Output:
array (
100 =>
array (
0 =>
array (
'AVA_Date' =>
array (
0 => '2019-04-18',
1 => '2019-04-22',
),
'ROO_Id' => 100,
'RAT_Id' => 9,
),
1 =>
array (
'AVA_Date' =>
array (
0 => '2019-04-20',
1 => '2019-04-21',
),
'ROO_Id' => 100,
'RAT_Id' => 10,
),
),
)

PHP - accesing to data of multi-dimensional array

I am trying to access data in a multi-dimenstional array.
I need to get values of this data (EC000001, EG000017, EN, EF007220) but I am struggling with foreach loops in PHP, especially when need to nested foreach Could you please help me and give me solution to access wanted data?
I need to loop over all $c's and then loop inside to get all needed data.This is how I collected value EC000001 before, but I believe that there is a better solution.
foreach ($c as $classCodes => $value) {
$classCode = key($c[$classCodes]); //classCode -> EC000001
}
Structure of array:
Array
(
**[EC000001]** => Array
(
[0] => **EG000017**
[1] => Array
(
[0] => Array
(
[0] => **EN**
[1] => Busbar terminal
)
[1] => Array
(
[0] => **nl-NL**
[1] => Aansluitklem stroomrail
)
)
[2] => Array
(
[0] => Array
(
[0] => **EF007220**
[1] => EU570448
[2] => Array
(
)
)
[1] => Array
(
[0] => EF007219
[1] => EU570448
[2] => Array
(
)
)
[2] => Array
(
[0] => EF000073
[1] =>
[2] => Array
(
[0] => EV009241
[1] => EV009472
)
)
[3] => Array
(
[0] => EF007092
[1] => EU570448
)
[4] => Array
(
[0] => EF004969
[1] => EU570126
)
)
)
)
I can not test it, but you can try with this inside the loop:
$value[0]; // -> 1
$value[1][0][0]; // -> 2
$value[1][1][1]; // -> 3
$EG000002Array[0][EG000001][0]
$EG000002Array[0][EG000001][1][0]
$EG000002Array[0][EG000001][1][1][1]
there are many ways to get array values from multi dimensional array
for example using foreach():
$flavors = array('Japanese' => array('hot' => 'wasabi',
'salty' => 'soy sauce'),
'Chinese' => array('hot' => 'mustard',
'pepper-salty' => 'prickly ash'));
// $culture is the key and $culture_flavors is the value (an array)
foreach ($flavors as $culture => $culture_flavors) {
// $flavor is the key and $example is the value
foreach ($culture_flavors as $flavor => $example) {
print "A $culture $flavor flavor is $example.\n";
}
}
or using for( ) :
$specials = array( array('Chestnut Bun', 'Walnut Bun', 'Peanut Bun'),
array('Chestnut Salad','Walnut Salad', 'Peanut Salad') );
// $num_specials is 2: the number of elements in the first dimension of $specials
for ($i = 0, $num_specials = count($specials); $i < $num_specials; $i++) {
// $num_sub is 3: the number of elements in each sub-array
for ($m = 0, $num_sub = count($specials[$i]); $m < $num_sub; $m++) {
print "Element [$i][$m] is " . $specials[$i][$m] . "\n";
}
}
the output should be like :
Element [0][0] is Chestnut Bun
Element [0][1] is Walnut Bun
Element [0][2] is Peanut Bun
Element [1][0] is Chestnut Salad
Element [1][1] is Walnut Salad
Element [1][2] is Peanut Salad
You can use recursion and regex to check if it's bolded :)
Notice we put& to $classCodes to pass it by reference and not
by value.
Function:
function get_bolded_data($c, &$classCodes = array()){
foreach($c as $k1 => $v1){
if(is_array($v1)){
//If $v1 is an array we call get_bolded_data() again and pass
//$v1 and $classCode
get_bolded_data($v1,$classCodes);
}else if(preg_match("/(\*\*).*(\*\*)/", $v1)){
$classCodes[] = $v1;
}
}
}
Usage:
$classCodes = array();
$c = array(
0 => array(
'**EC000001**' => array(
0 => '**EG000017**',
1 => array(
0 => array(
0 => '**EN**',
1 => 'Busbar terminal'
) ,
1 => array(
0 => '**nl-NL**',
1 => 'Aansluitklem stroomrail'
)
) ,
2 => array(
0 => array(
0 => '**EF007220**',
1 => 'EU570448',
2 => array()
) ,
1 => array(
0 => 'EF007219',
1 => 'EU570448',
2 => array()
) ,
2 => array(
0 => 'EF000073',
1 => '',
2 => array(
0 => 'EV009241',
1 => 'EV009472'
)
) ,
3 => array(
0 => 'EF007092',
1 => 'EU570448'
) ,
4 => array(
0 => 'EF004969',
1 => 'EU570126'
)
)
)
)
);
//Call our function
get_bolded_data($c, $classCodes);
Here is the result from var_dump:
array(4) {
[0]=>
string(12) "**EG000017**"
[1]=>
string(6) "**EN**"
[2]=>
string(9) "**nl-NL**"
[3]=>
string(12) "**EF007220**"
}

how to group a multidimensional array using a condition in php?

I have the following array
Array
(
[0] => Array
(
[shop] => 3
[price] => 332.00
)
[1] => Array
(
[shop] => 1
[price] => 3335.00
)
[2] => Array
(
[shop] => 3
[price] => 235.00
)
[3] => Array
(
[shop] => 1
[price] => 402.50
)
[4] => Array
(
[shop] => 3
[price] => 332.00
)
)
I need to group using shop and get get the minimum price of each shop in the array.
The expected result is as follows
Array
(
[0] => Array
(
[shop] => 3
[price] => 235.00
)
[1] => Array
(
[shop] => 1
[price] => 402.50
)
)
How will I do it?
You need to use additional variable
<?php
$arr = Array
(
0 => Array
(
'shop' => 3,
'price' => 332.00
),
1 => Array
(
'shop' => 3,
'price' => 232.00
),
2 => Array
(
'shop' => 1,
'price' => 232.00
),
3 => Array
(
'shop' => 3,
'price' => 432.00
),
4 => Array
(
'shop' => 1,
'price' => 132.00
),
);
$filtered = array();
foreach($arr as $prices){
if(FALSE === isset($filtered[$prices['shop']]) || $filtered[$prices['shop']]['price'] > $prices['price']){
$filtered[$prices['shop']] = $prices;
}
}
$filtered = array_values($filtered);
print_r($filtered);
This is very fast example how you can achieve this
It's rather simple.
Create a new array where you will host your stores as keys, and prices as values. What you want to do is to go through each element and first if the key does not exists in your new array, add it and its value. If however the key already exists, check if the current value is lower, and save it if true.
$grouped = [];
foreach ($arr as $k => $v) {
foreach ($k as $key => $value) {
if (isset($grouped[$key])) {
if ($value < $grouped[$key]) {
$grouped[$key] = $value;
}
} else {
$grouped[$key] = $value;
}
}
}
Your new array will look like this (store => price):
[
1 => 402.50,
3 => 235.00
]

How to merge array by value

I can generate array from mysql, if there is a way for making it easy. I get rows and currently I am rendering like that, if there is a way to generate on fly
3, 0.4311 |
3, 0.1803 |
4, 0.1149 |
4, 0.0775 |
5, 0.4291 |
5, 0.5100|
Considering this array, how to merge it :
Array
(
[0] => Array
(
[channel_id] => 3
[value] => 0.4311
)
[1] => Array
(
[channel_id] => 3
[value] => 0.1803
)
[2] => Array
(
[channel_id] => 4
[value] => 0.1149
)
[3] => Array
(
[channel_id] => 4
[value] => 0.0775
)
...
)
so it will look like this this:
Array
(
[0] => Array
(
[channel_id] => 3
[value] => 0.4311
[value] => 0.1803
)
[1] => Array
(
[channel_id] => 4
[value] => 0.1149
[value] => 0.0775
)
)
Here is the code that I generate this array:
while($row = $result->fetch_assoc()) {
$array[] = array('channel_id'=>$row['channel_id'],'value'=>$row['value'] );
}
OK this seem impossible, but this is closed I could get:
$channels_byid = array();
foreach($array as $v){
#$channel = $channels_byid[$v['channel_id']];
if ($array){
if(!is_array($channel[0])){
unset($channels_byid[$v['channel_id']]);
$channels_byid[$v['channel_id']] = $channel;
}
$channels_byid[$v['channel_id']][] = $v;
} else {
$channels_byid[$v['channel_id']] = $v;
}
}
print_r($channels_byid);
Which outputs:
[3] => Array
(
[0] => Array
(
[channel_id] => 3
[value] => 0.7513
)
[1] => Array
(
[channel_id] => 3
[value] => 0.7234
)
)
[4] => Array
(
[0] => Array
(
[channel_id] => 4
[value] => 0.9798
)
[1] => Array
(
[channel_id] => 4
[value] => 0.7625
)
)
Not exactly what you were after, but it might be useful. The channel_id becomes the top-level key and value becomes the values of a new array.
$data[] = array('channel_id' => 3, 'value' => 0.4311);
$data[] = array('channel_id' => 3, 'value' => 0.1803);
$data[] = array('channel_id' => 4, 'value' => 0.1149);
$data[] = array('channel_id' => 4, 'value' => 0.0775);
foreach($data as $k => $v) {
$merge[$v['channel_id']][] = $v['value'];
}
And the result of $merge is:
array(2) {
[3]=> array(2) {
[0]=> float(0.4311)
[1]=> float(0.1803)
}
[4]=> array(2) {
[0]=> float(0.1149)
[1]=> float(0.0775)
}
}

How can i check the unique key and value in this array

Array (
[0] => Array ( [2] => 3 )
[1] => Array ( [12] => 32 )
[2] => Array ( [2] => 3 )
[3] => Array ( [24] => 42 )
);
How can i get the output as unique key value. I need to remove the duplicate values.
I need the o/p like this
Array (
[0] => Array ( [2] => 3 )
[1] => Array ( [12] => 32 )
[2] => Array ( [24] => 42 )
);
array_reduce is likely designed for this purpose:
$a = [ [ 2 => 3 ], [ 3 => 4 ], [ 3 => 15 ], [ 2 => 3 ] ];
array_reduce($a, function($memo, $el) {
if(false === array_search($el, $memo)) array_push($memo, $el);
return $memo;
}, array())
#⇒ array(3) {
# [0] =>
# array(1) {
# [2] =>
# int(3)
# }
# [1] =>
# array(1) {
# [3] =>
# int(4)
# }
# [2] =>
# array(1) {
# [3] =>
# int(15)
# }
#}
Try this:
$array = array(
array(2 => 3),
array(12 => 32),
array(2 => 3),
array(24 => 32)
);
echo 'before array_unique_multi:' . "\n";
print_r($array);
echo 'after array_unique_multi:' . "\n";
print_r(array_unique_multi($array));
function array_unique_multi($array)
{
$hashAry = array();
foreach($array as $k=>$v){
$hash = md5(serialize($v));
if(in_array($hash, $hashAry)) unset($array[$k]);
else $hashAry[]=$hash;
}
$array = array_values($array);
return $array;
}
Output:
before array_unique_multi:
Array
(
[0] => Array
(
[2] => 3
)
[1] => Array
(
[12] => 32
)
[2] => Array
(
[2] => 3
)
[3] => Array
(
[24] => 32
)
)
after array_unique_multi:
Array
(
[0] => Array
(
[2] => 3
)
[1] => Array
(
[12] => 32
)
[2] => Array
(
[24] => 32
)
)
You can use the function array_unique.
http://php.net/manual/fr/function.array-unique.php
foreach ($myMultiArray as $index => $doublonArray) {
$myMultiArray[$index] = array_unique($doublonArray);
}
Use this. This will store all the different key / value pairs in the new array.
$test = array(
array(2 => 3),
array(12 => 32),
array(2 => 3),
array(24 => 42)
);
$tmpArray = array();
$newArray = array();
foreach ($test as $elements) {
foreach ($elements as $key => $val) {
if (!array_key_exists($key, $tmpArray) || $tmpArray[$key] !== $val) {
$tmpArray[$key] = $val;
}
}
}
foreach ($tmpArray as $key => $val) {
$newArray[] = array($key => $val);
}
var_dump($newArray);
Output:
array
0 =>
array
2 => int 3
1 =>
array
12 => int 32
2 =>
array
24 => int 42
$check_arr = Array (
[0] => Array ( [13] => 1 )
[1] => Array ( [13] => 3 )
[2] => Array ( [13] => 1 )
[3] => Array ( [10] => 3 )
) ;
print_r(array_unique($check_arr));
This my result.
Array ( [0] => Array ( [13] => 1 ) );

Categories