Simplifying the array by removing same key values - php

I have a Array like this
Array
(
[0] => Array
(
[vendor_id] => 2
[vendor_total_order] => 80
)
[1] => Array
(
[vendor_id] => 2
[vendor_total_order] => 100
)
[2] => Array
(
[vendor_id] => 1
[vendor_total_order] => 150
)
[3] => Array
(
[vendor_id] => 3
[vendor_total_order] => 80
)
[4] => Array
(
[vendor_id] => 5
[vendor_total_order] => 150
)
[5] => Array
(
[vendor_id] => 1
[vendor_total_order] => 110
)
)
I want to simplify this array in such a way that if the 'vendor_id' are same for two values there there accumulated/summed value should be assigned to 'vendor_total_order' to that 'vendor_id'(basically we are removing values which are having same vendor_id with the total value of duplicates).
So when i provide the above array as input the output should look like as follow
Array
(
[0] => Array
(
[vendor_id] => 2
[vendor_total_order] => 180
)
[1] => Array
(
[vendor_id] => 1
[vendor_total_order] => 260
)
[2] => Array
(
[vendor_id] => 3
[vendor_total_order] => 80
)
[3] => Array
(
[vendor_id] => 5
[vendor_total_order] => 150
)
)
How can i do this ?

You just need to group them using a foreach. Example:
$total = array();
foreach ($array as $key => $value) {
if(!isset($total[$value['vendor_id']])) {
$total[$value['vendor_id']] = array('vendor_id' => $value['vendor_id'], 'vendor_total_order' => 0);
}
$total[$value['vendor_id']]['vendor_total_order'] += $value['vendor_total_order'];
}
$total = array_values($total); // simple reindex
echo '<pre>';
print_r($total);
Sample Output

Your best bet is to write a custom script that does the following:
Creates an empty new "result" array
Iterates over the current array and for each item:
If the item doesn't exist in result, insert it, otherwise update the total_value value as the sum of it's current value and the new item.
Save the result array

Related

Sync array values across all related array keys

I have a PHP array with the following data
Array
(
[3] => Array
(
[0] => 4095
[2] => 651
)
[4095] => Array
(
[0] => 3
)
[651] => Array
(
[0] => 4432
)
[4432] => Array
(
[0] => 651
)
[92] => Array
(
[0] => 45
)
)
The above array has keys as student_id and the values are also student_id creating a circular relation. What I am trying to achieve is all the student_id has the same set of student_id values. Basically if student_id 3 is related to 4095, 4432 & 651, then, in turn, each of these values has to have 3 among them including other student_id from 3. The below output demonstrates what I am trying to achieve.
Array
(
[3] => Array
(
[0] => 4095
[1] => 4432
[2] => 651
)
[4095] => Array
(
[0] => 3
[1] => 4432
[2] => 651
)
[651] => Array
(
[0] => 3
[1] => 4432
[2] => 4095
)
[4432] => Array
(
[0] => 3
[1] => 4095
[2] => 651
)
[92] => Array
(
[0] => 45
)
[45] => Array
(
[0] => 92
)
)
Explanation of output
The array keys 3, 4095, 651 & 4432 are related to each other either directly or via a common relation (indirect), so will have common set of values (siblings). The key 92 in input array has a value (sibling) of 45, so in a resultant array, a new key 45 will be added to array with the inverse relation as well.
What I have tried so far
I have tried to do it with this code
$syncedSiblings = [];
foreach ($studentsWithSiblings as $sid => $siblings) {
$all = map_assoc(array_merge([$sid], array_keys($siblings)));
foreach ($all as $studentId) {
if (isset($syncedSiblings[$studentId])) {
$old = $syncedSiblings[$studentId];
$syncedSiblings[$studentId] = array_unique(array_merge($old, array_except($all, $studentId)));
} else {
$syncedSiblings[$studentId] = array_unique(array_except($all, $studentId));
}
}
}
Where $studentsWithSiblings has the above array & array_except returns array without the passed values as second argument.
This is the output I am getting right now
Array
(
[3] => Array
(
[0] => 4095
[1] => 651
)
[4095] => Array
(
[0] => 3
[1] => 651
)
[651] => Array
(
[0] => 3
[1] => 4095
[2] => 4432
)
[4432] => Array
(
[0] => 651
)
[92] => Array
(
[0] => 45
)
)
Any help with this will be highly appreciated.
If I've understood you correctly, then this possible to achieve with recursion:
function getChildren($ind_ar, $prev_ar, $data, $rem){
$tmp = [];
$mark = 0;
foreach($ind_ar as $ind){
foreach($data[$ind] as $new_val){
if(!in_array($new_val,$prev_ar) && $new_val != $ind && $new_val != $rem){
$mark = 1;
$tmp[] = $new_val;
}
foreach($data[$new_val] as $new){
if(!in_array($new,$prev_ar) && $new != $ind && $new != $rem){
$mark = 1;
$tmp[] = $new;
}
}
}
}
$res_ar = $prev_ar;
if(!empty($tmp)) $res_ar = array_unique(array_merge($tmp,$prev_ar));
if($mark) $res_ar = getChildren($tmp,$res_ar,$data, $rem);
return $res_ar;
}
You can use this function in this way:
$data = array( 3 => [4095, 651], 4095 => [3], 651 => [4432], 4432 => [3, 651], 92 => [45], 45 => [92], );
foreach($data as $in => &$data_val) {
$data_val = getChildren([$in],$data_val,$data, $in);
sort($data_val);
}
Demo
Output:
Array
(
[3] => Array
(
[0] => 651
[1] => 4095
[2] => 4432
)
[4095] => Array
(
[0] => 3
[1] => 651
[2] => 4432
)
[651] => Array
(
[0] => 3
[1] => 4095
[2] => 4432
)
[4432] => Array
(
[0] => 3
[1] => 651
[2] => 4095
)
[92] => Array
(
[0] => 45
)
[45] => Array
(
[0] => 92
)
)
Two nested loops over the data. If the keys are different, then check if the key of the inner loop is already contained in the data array of the outer key element - if not, add it.
$data = json_decode('{"3":{"0":4095,"2":651},"4095":[3],"651":[4432],"4432":{"1":651}}', true);
foreach($data as $key_outer => $val_outer) {
foreach($data as $key_inner => $val_inner) {
if($key_outer != $key_inner && !in_array($key_inner, $data[$key_outer])) {
$data[$key_outer][] = $key_inner;
}
}
}
var_dump($data);
This gets you
array (size=4)
3 =>
array (size=3)
0 => int 4095
2 => int 651
3 => int 4432
4095 =>
array (size=3)
0 => int 3
1 => int 651
2 => int 4432
651 =>
array (size=3)
0 => int 4432
1 => int 3
2 => int 4095
4432 =>
array (size=3)
1 => int 651
2 => int 3
3 => int 4095
I am assuming a specific order of the elements in those sub-items is not actually required. If it is, then please sort them yourself as desired afterwards or in between (depending on what exactly you need, f.e. sort($data[$key_outer]); after the inner loop would get you the IDs in all sub-arrays sorted ascending.)

How to replace arrays of multidimensional array with items of that array using php?

In the multi-dimensional array below how would I replace the top level indices [0] [1] & [2] with their respective values from [SUB1]
Array
(
[0] => Array
(
[SUB1] => AAA111
[SUB2] => Description 1
[SUB3] => 10
)
[1] => Array
(
[SUB1] => BBB222
[SUB2] => Description 2
[SUB3] => 20
)
[2] => Array
(
[SUB1] => CCC333
[SUB2] => Description 3
[SUB3] => 30
)
)
I've managed to use $sub1 = array_column( $array, 'SUB1' ); to get the below array, but I'm not sure if a simple function exists to use it to replace the indices in the original array with the values.
Array
(
[0] => AAA111
[1] => BBB222
[2] => CCC333
)
Edit:
Desired output:
Array
(
[AAA111] => Array
(
[SUB2] => Description 1
[SUB3] => 10
)
[BBB222] => Array
(
[SUB2] => Description 2
[SUB3] => 20
)
[CCC333] => Array
(
[SUB2] => Description 3
[SUB3] => 30
)
)
Please check below example, Where $test is equal to your main array.
$output = [];
foreach ($test as $t) {
$first = reset($t);
$remaining = array_shift($t);
$output[$first] = $t;
}
echo '<pre>';
print_r($output);

Array_push within foreach loop overwites earlier arrey values

I'm trying to build a multidimentional array of matches found within a foreach loop. After one loop the array is correct but on the second loop, the earlier array values are overwritten. What is going on?
$matches = array();
foreach ($promotions as $promotion) {
$matches = array();
foreach ($saleitems as $saleitem) {
if ($saleitem['PROMO_CODE'] == $promotion['SALES_CODE']) {
$matches[] = array('ID'=>$saleitem['ID'], "LINENO"=>$saleitem['LINE'], "SAVING"=>"0", 'SALEINC'=>$saleitem['SALEINC']);
}
}
//other code with works out discount etc.
$linesarray[] = array("CODE"=>$promotion['CODE'], "LINES"=>$matches);
print_r($linesarray);
echo "<p>";
}
Outputs this:
Array ( [0] => Array ( [CODE] => 5 [LINES] => Array ( [0] => Array ([ID] => 51016 [LINENO] => 4 [SAVING] => 5 [SALEINC] => 15.00 ) [1] => Array ([ID] => 51013 [LINENO] => 3 [SAVING] => 5 [SALEINC] => 15.00 ) ) ) )
Array ( [0] => Array ( [CODE] => 5 [LINES] => Array ( [0] => Array ( [ID] => 51016 [LINENO] => 4 [SAVING] => 5 [SALEINC] => 15.00 ) [1] => Array ([ID] => 43930 [LINENO] => 2 [SAVING] => 0 [SALEINC] => 16.00 ) ) ) [1] => Array ( [CODE] => 7 [LINES] => Array ( [0] => Array ([ID] => 43914 [LINENO] => 1 [SAVING] => 6 [SALEINC] => 16.00 ) [1] => Array ([ID] => 43930 [LINENO] => 2 [SAVING] => 6 [SALEINC] => 16.00 ) ) ) )
As you can see LINENO 3 has been replaced the first array on second loop. Why?
The $matches = array(); inside the loop will reinitialize the array. The $matches = array(); before the loop is fine.
$matches[] = array('ID'=>$saleitem['ID'], "LINENO"=>$saleitem['LINE'], "SAVING"=>"0", 'SALEINC'=>$saleitem['SALEINC']);
I see you fixed "SAVING"=>"0" but your outputs have other result [SAVING] => 5 Did you run your code again?
You should give us $promotions and $saleitems array.

Taking Value from one array with keys aret the valuses of another another array in php

I have one array called $stocknumb
$stocknumb= Array ( [0] => 102 [1] => 103 [2] => 104 )
Another array called $price it contains both $stocknumb as well as price
$price=Array ( ['102'] => Array ( [0] => 2000 ) ['103'] => Array ( [0] => 3 ) ['104'] => Array ( [0] => 4000 ) )
Now i would like to get prices for only stock numbers which are in $stocknumb array. Both price and stock number are in $price array.
How to get it in PHP.
See array_column function (php >= 5.5) :
$price= array(
102 => array(0 => 2000),
103 => array(0 => 3),
104 => array(0 => 4000)
);
$array_price = array_column ($price, 0);
print_r($array_price);
/*Array
(
[0] => 2000
[1] => 3
[2] => 4000
)
*/
If you don't use php 5.5, see :
https://github.com/ramsey/array_column/blob/master/src/array_column.php
If you want final data as array then with conventional way of looping could be done as
$stocknumb= Array ( 0 => 102, 1 => 103, 2 => 104 ) ;
$price=Array ( '102' => Array ( 0 => 2000 ), '103' => Array ( 0 => 3 ), '104' => Array ( 0 => 4000 ) );
$final_array = array() ;
foreach($stocknumb as $key=>$val){
if(array_key_exists($val,$price)){
$final_array[$val] = $price[$val][0];
}
}
print_r($final_array);
Output
Array ( [102] => 2000 [103] => 3 [104] => 4000 )
You can use array intersect function
$stocknumb= array ( 102, 103 );
// Make the key same as the value.
$stocknumb = array_combine($stocknumb, $stocknumb);
$price= array (102 => array (2000), 103 => array (3), 104 => array (4000 ));
$filtered = array_intersect_key($price, $stocknumb);
A single line of code with array_flip() and array_key_intersect() will suffice
$new_arr=array_intersect_key($price, array_flip($stocknumb));
OUTPUT :
Array
(
[102] => Array
(
[0] => 2000
)
[103] => Array
(
[0] => 3
)
[104] => Array
(
[0] => 4000
)
)
<?php
foreach($price as $key => $value) {
if(in_array($key, $stocknumb)) {
echo $value[0];
}
}
DEMO

How can I efficiently get a sub array to be the main array without a foreach loop?

Here's my array:
Array
(
[0] => Array
(
[same_key] => 1000
)
[1] => Array
(
[same_key] => 1001
)
[2] => Array
(
[same_key] => 1002
)
[3] => Array
(
[same_key] => 1003
)
)
I'd like to get the following without using a foreach loop. Is this possible?
Array
(
[0] => 1000
[1] => 1001
[2] => 1002
[3] => 1003
)
Any tips?
The following will do the trick
$myArray = Array
(
0 => Array
(
'adfadf'=> 1000
),
1 => Array
(
'adfadf' => 1001
),
2 => Array
(
'adfadf' => 1002
),
3 => Array
(
'adfadf' => 1003
)
);
$myArray = array_map('current', $myArray));
you can do this by $array = array_map('current', $array);
live example
output

Categories