PHP multiply values of a multidimensional array - php

I've tried searching for this as I don't think it's that unique that no one has tried to do it. I just can't figure out the right keywords to search for to find my answer!
I have this array
array(
0 => array(
'oranges'=> 4.00,
'apples' => 2.00,
),
1 => array(
'oranges' => 2.00,
'apples' => 1.82,
'peaches' => 1.2,
),
2 => array(
'oranges' => 2.20,
),
);
What I want to do is find the value of all the oranges values multiplied together so (4 * 2 * 2.20) and all the values of apples multiplied together so (2 * 1.82).
The amount of arrays of values is variable and the amount of values inside the arrays is variable.

This uses a combination of foreach, isset, and your run-of-the-mill if/else statements.
$products = array();
foreach ($array as $a) {
foreach ($a as $key => $value) {
if (!isset($products[$key])) $products[$key] = $value;
else $products[$key] = $products[$key] * $value;
}
}
var_dump($products);
Should be self-explanatory since all you're doing is taking the product of all of the lowest level elements with the same keys.

Though sjagr’s answer is the best solution possible, I have an alternative approach with array_column (PHP 5 >= 5.5.0) which requires only one foreach loop:
<?php
$arr = array(
array(
"oranges" => 4.00,
"apples" => 2.00
),
array(
"oranges" => 2.00,
"apples" => 1.82,
"peaches" => 1.2
),
array(
"oranges" => 2.20
)
);
$_arr = array();
foreach(array("oranges", "apples", "peaches") as $val){
$_arr[$val] = array_product(array_column($arr, $val));
}
print_r($_arr);
?>
The result will be:
Array
(
[oranges] => 17.6
[apples] => 3.64
[peaches] => 1.2
)
Demo: https://eval.in/82322

Related

php array_multisort(): Array sizes are inconsistent

How can I use the php array_multisort to sort arrays like this? I can't find any examples with this type of arrays. I have tried different avenues but I keep getting the error array_multisort(): Array sizes are inconsistent.
$array= Array (
"Arnold" => Array ( "index" => 2, "games_played" => 1, "score" => 5 ),
"Chris" => Array ( "index" => 1, "games_played" => 1, "score" => 5 ),
"Mike" => Array ( "index" => 0, "games_played" => 2, "score" => 5 )
);
I think you're taking it the wrong way. array_multisort is not what would be a "sort by" in other languages (i.e: sort array elements by some properties), instead it sorts the first array, and reverberate that order to all following arrays. And in case of equality it checks the corresponding values of the second arrays, etc...
If you want to order your example by score (desc), then by game played, then by index (and then by name, but this should never happen since indexes are uniques) you should do:
$array= Array (
"Arnold" => Array ( "index" => 2, "games_played" => 1, "score" => 5 ),
"Chris" => Array ( "index" => 1, "games_played" => 1, "score" => 5 ),
"Mike" => Array ( "index" => 0, "games_played" => 2, "score" => 5 )
);
$names = [];
$indexes = [];
$games_played = [];
$scores = [];
foreach ($array as $name => $player) {
$names[] = $name;
$indexes[] = $player['index'];
$games_played[] = $player['games_played'];
$scores[] = $player['score'];
}
array_multisort(
$scores, SORT_DESC,
$games_played,
$indexes,
$names,
$array /* This line will sort the initial array as well */
);

Merge second array into first array where row value in first array matches row key in second array

I would like to merge the associative elements from my second array into my first array where the second array's subarray key matches a row's epg_channel_id value.
First array:
[
[
'num' => 1,
'name' => 'name 1',
'epg_channel_id' => 'ch111',
'added' => '1505435915',
],
[
'num' => 2,
'name' => 'name 2',
'epg_channel_id' => 'ch222',
'added' => '1505435915',
],
[
'num' => 3,
'name' => 'name 3',
'epg_channel_id' => 'ch333',
'added' => '1505435915',
],
[
'num' => 4,
'name' => 'name 4',
'epg_channel_id' => 'ch444',
'added' => '1505435915'
]
]
And the second array:
[
['ch000' => 'Um9jayBJbiBSaW8='],
['ch111' => 'Um9jayBJbiBSaW8='],
['ch222' => 'Um9jayBJbiBSaW8='],
['ch333' => 'Um9jayBJbiBSaW8='],
['ch444' => 'Um9jayBJbiBSaW8=']
]
Desired output (for one row):
Array
(
[0] => Array
(
[num] => 1
[name] => name 1
[epg_channel_id] => ch111
[added] => 1505435915
[ch111] => Um9jayBJbiBSaW8=
)
...
)
I tried array_recursive, array merge and not works.
If the corresponding indexes in both arrays are guaranteed to have the same channel id, this will work quite efficiently. For example, if $array1[0] is guaranteed to have the same channel id as $array2[0] this solution will work nicely:
$combined = [];
foreach($array1 as $key=>$val){
$combined[$key] = $val + $array2[$key];
}
However, if the corresponding indexes are not guaranteed to have the same channel ids, this solution will not work, and you'll need to use one of the other posted answers.
One last note if you do use this method is that if the arrays are different sizes, you will want the largest one to be $array1. So, just do a comparison to see which has the most elements.
You have to loop over two arrays to get desired result: as you have to match epg_channel_id of first array to second arrays inner key
$arr1 = Array
(
0 => Array
(
"num" => 1,
"name" => "name 1",
"epg_channel_id" => "ch111",
"added" => "1505435915",
),
1 => Array
(
"num" => 2,
"name" => "name 2",
"epg_channel_id" => "ch222",
"added" => "1505435915",
),
2 => Array
(
"num" => 3,
"name" => "name 3",
"epg_channel_id" => "ch333",
"added" => "1505435915",
),
3 => Array
(
"num" => 4,
"name" => "name 4",
"epg_channel_id" => "ch444",
"added" => "1505435915",
),
);
$arr2 = Array
(
0 => Array
(
"ch000" => "Um9jayBJbiBSaW8="
),
1 => Array
(
"ch111" => "Um9jayBJbiBSaW8="
),
2 => Array
(
"ch222" => "Um9jayBJbiBSaW8="
),
3 => Array
(
"ch333" => "Um9jayBJbiBSaW8="
),
4 => Array
(
"ch444" => "Um9jayBJbiBSaW8="
),
);
$new_array = array();
foreach($arr1 as $key=>$value)
{
foreach($arr2 as $key1=>$value1)
{
foreach($value1 as $key2=>$value2)
{
if($key2 == $value['epg_channel_id'])
{
$value[$key2]=$value2;
}
}
}
$new_array[$key]=$value;
}
print_r($new_array);
DEMO
You can key exists or not using array_key_exists in second array then add it to new array
Working Demo: https://eval.in/863359
$array = Array
(
Array
(
'num' => 1,
'name' => 'name 1',
'epg_channel_id' => 'ch111',
'added' => '1505435915',
),
Array
(
'num' => 2,
'name' => 'name 2',
'epg_channel_id' => 'ch222',
'added' => '1505435915',
),
Array
(
'num' => 3,
'name' => 'name 3',
'epg_channel_id' => 'ch333',
'added' => '1505435915',
),
Array
(
'num' => 4,
'name' => 'name 4',
'epg_channel_id' => 'ch444',
'added' => '1505435915'
)
);
$array2 = Array
(
Array
(
'ch000' => 'Um9jayBJbiBSaW8='
),
Array
(
'ch111' => 'Um9jayBJbiBSaW8='
),
Array
(
'ch222' => 'Um9jayBJbiBSaW8='
),
Array
(
'ch333' => 'Um9jayBJbiBSaW8='
),
Array
(
'ch444' => 'Um9jayBJbiBSaW8='
)
);
$newArray =[];
foreach ($array as $key => $value) {
foreach ($array2 as $key2 => $value2) {
if (array_key_exists($value['epg_channel_id'], $value2)) {
$value[$value['epg_channel_id']] = $value2[$value['epg_channel_id']];
}
}
$newArray[] = $value;
}
echo "<pre>";
print_r($newArray);
array_merge_recursive works well for associated array that have keys are string. Numeric keys will be appended. From php.net
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.
You have to convert your array to string keys, or using one loop to merge child arrays one by one.
Try this . I hope it will solve your problems. I have tested it.
foreach ($array1 as $key => $value){
// echo $key;
foreach ($array2 as $i =>$item){
foreach ($item as $j=>$subitem){
if($value['epg_channel_id'] == $j){
$array1[$key][$j] = $subitem;
}
}
}
}
print_r($array1);
try to read the value of 'epg_channel_id' from array1
and insert it to array1 itself from getting 'ch111' from array2
$ch_name = $array1[$i]['epg_channel_id'];
$id = $array1[$i]['num'];
$ch_value = $array2[$id]['$ch_name'];
$array1[$i]["$ch_name"] = $ch_value;
try to put in foreach for every array
$new_arr = [];
foreach($arr1 as $val){
foreach($arr2 as $val2){
if(array_key_exists($val['epg_channel_id'], $val2)){
$val[$val['epg_channel_id']] = $val2[$val['epg_channel_id']];
break;
}
}
$new_arr[] = $val;
}
print_r($new_arr);
The bad news is that your second array is not suitably structured to serve as a lookup array. The good news is that the step to flatten the structure into a simple associative array is quite easy.
Once the lookup is declared, just use a loop and modify-by-reference as you use array union syntax to append the desired key-value pairs.
I do not recommend any answers that are using nested loops -- they will not perform efficiently.
Code: (Demo)
$lookup = array_merge(...$array2);
foreach ($array as &$row) {
$row += [$row['epg_channel_id'] => $lookup[$row['epg_channel_id']]];
}
var_export($array);

cakephp find the array elements by meeting the conditions between two arrays?

I have two arrays. One array consists of Id & another array consists of the values & keys. For example. I have a variable called Fruit_id, which consists of:
array(
'fruit_id' => array(
(int) 0 => '3',
(int) 1 => '4'
)
)
and another array called fruits, which consists of:
array(
'values' => array(
(int) 1 => ' Apple',
(int) 2 => 'Banana',
(int) 3 => 'Orange',
(int) 4 => 'Mango'
),
'keys' => array(
(int) 0 => (int) 1,
(int) 1 => (int) 2,
(int) 2 => (int) 3,
(int) 3 => (int) 4
)
)
So, based on fruit_id, I want to have Orange & Mango stored in a variable. How can this be achieved?
as per my understanding you can try below code
$fruits = array();
foreach ($array1['fruit_id'] as $key1 => $value1)
{
foreach ($array2['values'] as $key2 => $value2)
{
if ($value1 == $key2)
{
$fruits[$value1] = $value2;
}
}
}
print_r($fruits);
This will return Array ( [3] => Orange [4] => Mango )
Let me know if this helps you out or any changes needed
You could achieve this easily without even using any loop. Use array_filter() instead.
$array1 = array("fruit_id" => array(3, 4));
$array2 = array(
"values" => array(1 => "Apple",2 => "Banana",3 => "Orange", 4 => "Mango"),
"keys" => array(1,2,3,4)
);
/* Filter elements from $array2['values'] whose keys are present in $array1['fruit_id'] */
$result = array_filter($array2['values'], function($v, $k) use ($array1){
return in_array($k, $array1['fruit_id']);
}, ARRAY_FILTER_USE_BOTH);
echo implode(' & ', $result); // Convert array to string separated by '&'

Subtract row values in Array2 from specific row values in Array1

I would like to subtract the quantity of $array2 from the stocks of $array1.
$array1= ([product_id]=>4, [stocks]=>20)
$array2= ([product_id]=>4, [quantity]=>3)
So that would be:
$array1= ([0]=> 4, [1] => 20);
$array2= ([0]=> 4, [1] => 3);
And then the output should be:
$array1= ([0]=> 4, [1] => 17);
Your array structure looks slightly different with multiple records, the code works out like this in an ugly manner. I'm assuming you're talking about something like this:
$array1 = array(
0=>array('product_id'=>4, 'stocks'=>20),
1=>array('product_id'=>5, 'stocks'=>60));
$array2 = array(
0=>array('product_id'=>4, 'quantity'=>3)
1=>array('product_id'=>5, 'quantity'=>30));
...It's a multi-dimensional array (typical for records pulled from a database).
foreach($array1 as $key=>$value){
foreach($array2 as $key2=>$value2) {
if($value['product_id']==$value2['product_id']){
$value['stocks'] -= $value2['quantity'];
//optimization to avoid searching this again.
unset($array2[$key]);
}
}}
With what you have given the following will do what you are asking for:
if($array1['product_id'] == $array2['product_id']) {
$array1['stocks'] -= $array2['quantity'];
}
If you need to loop through a bigger array then what I have given is only part of the larger puzzle.
Jesse's answer wasn't tested and will not provide the desired output because the "stocks" array wasn't being modified -- a copy of the array was being modified in the loop -- so if you try to print the result to screen, there would be no change.
To modify by reference, use & just before the value variable in the first loop.
Also the unset() key must come from the inner loop to be accurate.
Additionally, if the "sales" "product_id"s are unique, then breaking the inner loop upon matching will improve performance. (This is how array_search() works.)
Code: (Demo)
$stocks = [
['product_id'=>2, 'stocks'=>50],
['product_id'=>3, 'stocks'=>100],
['product_id'=>4, 'stocks'=>20],
['product_id'=>5, 'stocks'=>60]
];
$sales = [
['product_id'=>4, 'quantity'=>3],
['product_id'=>5, 'quantity'=>30]
];
foreach ($stocks as &$row) { // modify by reference
foreach ($sales as $k => $row2) { // search for product_id match
if ($row['product_id'] == $row2['product_id']) {
$row['stocks'] -= $row2['quantity']; // subtract
unset($sales[$k]); // eliminate match from lookup array
break; // assuming $sales['product_id'] values are unique
}
}
}
var_export($stocks);
Output:
array (
0 =>
array (
'product_id' => 2,
'stocks' => 50,
),
1 =>
array (
'product_id' => 3,
'stocks' => 100,
),
2 =>
array (
'product_id' => 4,
'stocks' => 17,
),
3 =>
array (
'product_id' => 5,
'stocks' => 30,
),
)
Alternatively, you can converted the sales array into a flattened, product_id-keyed array to serve as a lookup.
Code: (Demo)
$keyed = array_column($sales, 'quantity', 'product_id');
var_export($keyed);
echo "\n---\n";
foreach ($stocks as &$row) { // modify by reference
if (isset($keyed[$row['product_id']])) { // search for product_id match
$row['stocks'] -= $keyed[$row['product_id']]; // subtract
}
}
var_export($stocks);
Output:
array (
4 => 3,
5 => 30,
)
---
array (
0 =>
array (
'product_id' => 2,
'stocks' => 50,
),
1 =>
array (
'product_id' => 3,
'stocks' => 100,
),
2 =>
array (
'product_id' => 4,
'stocks' => 17,
),
3 =>
array (
'product_id' => 5,
'stocks' => 30,
),
)

Matching keys from one array to another and creating a new array with their values?

Hi I have two arrays the first one looks like this:
array(
00000 => array(
0 => 123,
1 => 456,
2 => 789,
)
11111 => array(
0 => 987,
1 => 654,
2 => 321,
)
My second array looks like this:
array(
00000 => 'apples',
11111 => 'bananas',
)
What am trying to do is match the keys from the 1st array with the keys in array 2nd then if they match take the values of key pair value array of the first array and make them keys for a brand new array and the values of the second array make them values for the brand new array. Something like this:
array(
123 => 'apples',
456 => 'apples',
789 => 'apples',
987 => 'bananas',
654 => 'bananas',
321 => 'bananas',
)
Any help thanks!
so im assuming u have 2 arrays (and you fixed second array to have unique keys)
$array3 = array (); //for the result
foreach ($array1 as $seg)
{
foreach ($seg as $key)
{
$array3[$key] = $array2[$seg];
}
}
Try this
$array = array(
"00000" => array(
0 => 123,
1 => 456,
2 => 789,
),
"11111" => array(
0 => 987,
1 => 654,
2 => 321,
)
);
$arr = array(
"00000" => 'apples',
"11111" => 'bananas',
);
$array3 = array();
foreach ($array as $keyas => $segs)
{
foreach ($segs as $key)
{
$array3[$key] = $arr[$keyas];
}
}
echo "<pre>";
print_r($array3);
unset($array3);
Output :
Array
(
[123] => apples
[456] => apples
[789] => apples
[987] => bananas
[654] => bananas
[321] => bananas
)
Hi actually i did some research on php.net found a solution:
$array3 = array_keys($array1);
$array4 = array_keys($array2);
$array5 = array_intersect($array3, $array4)
$array6 = array();
foreach($array5 as $id) {
foreach($array1[$id] as $userId) {
$array6[$userId] = $array2[$id]
}
}
Probably made more arrays than needed but this works and matches keys of both arrays before assigning values to new array.
Thanks to all that answered and helped!

Categories