Sum of columns in multidimensional array without loops - php

I'm used to analysing data in R and have a hard time figuring out array in PHP.
Given the following array ($dat), what is the easiest way to get the total number of all females?
print("<pre>".print_r($dat,true)."</pre>");
Array
(
[0] => Array
(
[0] => female
[1] => blue
[2] => 62
)
[1] => Array
(
[0] => female
[1] => red
[2] => 22
)
[2] => Array
(
[0] => male
[1] => blue
[2] => 21
)
)
I'm doing this:
foreach($dat as $row) {
if($row[0]=='female') {
$females = $females + $row[2];
}
}
But there must be a way without loops!
Isn't there something like sum($dat[][2])?
Result for this sample should be 84

It seems I misinterpreted your question...
To obtain the sum, you can use array_reduce instead of a foreach loop (although it's not going to be much of an improvement):
array_reduce($dat, function($prev,$curr){return $prev+($curr[0]==='female'?$curr[2]:0);}, 0);
To obtain the number of elements containing 'female', You could use count with array_filter:
echo count(array_filter($dat, function($x){return in_array('female', $x);}));
This filters the array for any sub-arrays that contain the string female and returns the number of elements.
If you're sure that the string 'female' is always the zeroth element of the array, you could simplify the function slightly:
echo count(array_filter($dat, function($x){return $x[0]==='female';}));

You can array_reduce your array to a sum that way :
$array[0] = array('female', 2);
$array[1] = array('female', 5);
$array[2] = array('male', 2);
$sum = array_reduce($array, function ($value, $item) {
if ($item[0] == 'female') $value += $item[1];
return $value;
}, 0);
var_dump($sum);
Output :
7

Related

How to merge two arrays and sum the values of duplicate keys? [duplicate]

This question already has answers here:
How to merge two arrays by summing the merged values [duplicate]
(3 answers)
Closed 5 months ago.
I would like to merge array by conditions. If array keys match then add the values, if not then retain the value.
Here are my arrays:
Array1
(
[1] => 199
[3] => 1306
[5] => 199
)
Array2
(
[3] => 199
[4] => 199
)
My desired result is:
Result
(
[1] => 199
[3] => 1505
[4] => 199
[5] => 199
)
I used if-else conditions, but it's repeating the value which is already matched.
Here is my coding attempt:
$all=array();
foreach($sall as $sskey => $ssvalue){
foreach($upgradesall as $uukey => $uuvalue){
//$sskey==$uukey?$all[] = array("id"=>$sskey, "amount"=>$ssvalue+$uuvalue):($sskey!=$uukey? $all[] = array("id"=>$sskey, "amount"=>$ssvalue):($uukey!=$sskey?$all[] = array("id"=>$uukey, "amount"=>$uuvalue):''));
if($sskey===$uukey){
$all[] = array("id"=>$sskey, "amount"=>$ssvalue+$uuvalue);
}elseif($sskey!=$uukey){
$all[] = array("id"=>$sskey, "amount"=>$ssvalue);
}elseif($uukey!=$sskey){
$all[] = array("id"=>$uukey, "amount"=>$uuvalue);
}
}
}
I think the problem is simpler than it looks. You really only need a conditional to preclude undefined offset notices. Just iterate all keys and values in both arrays and add the values to the corresponding key in the merged array.
foreach ([$a1, $a2] as $a) { // iterate both arrays
foreach ($a as $key => $value) { // iterate all keys+values
$merged[$key] = $value + ($merged[$key] ?? 0); // merge and add
}
}
Really, the line that actually does the addition ($merged[$key] = $value + ($merged[$key] ?? 0);) could be reduced to $merged[$key] += $value;. That would still work, but it would produce a bunch of undefined offset notices. So instead we can set the key equal to the value plus either the previous value (if it exists) or zero.
If you're still using PHP 5, you can use a ternary instead of the null coalescing operator (??), like this:
$merged[$key] = $value + (isset($merged[$key]) ? $merged[$key] : 0);
The output won't be in the same order shown in your desired result, but you can use ksort($merged); to accomplish that
First you can merge the arrays by merging all values in the same key:
$allKeys = array_unique(array_merge(array_keys($arr1),array_keys($arr2)));
$result = [];
foreach ($allKeys as $key) {
$result[$key] = [];
if (array_key_exists($key,$arr1)) {
$result[$key][] = $arr1[$key];
}
if (array_key_exists($key,$arr2)) {
$result[$key][] = $arr2[$key];
}
}
This will result in:
Array
(
[1] => Array
(
[0] => 199
)
[3] => Array
(
[0] => 1306
[1] => 199
)
[5] => Array
(
[0] => 199
)
[4] => Array
(
[0] => 199
)
)
Then you can map them according to your conditions:
$endResult = array_map('array_sum',$result);
Result:
Array
(
[1] => 199
[3] => 1505
[5] => 199
[4] => 199
)
If you want the keys to be sorted you can run them through a ksort as well
Check the code:
http://sandbox.onlinephpfunctions.com/code/3eb23310f0fd8de8174a5caf8b2b91d4b7562b6b
You could achieve that by
$all = array_merge($arr1,$arr2); // existing elements in arr1 are replaced by arr2 else merge into new array_merge
//then add replaced elememnts value
foreach($arr1 as $k=>$v)
{
if(array_key_exists($k,$all))
{
$all[$k] = $all[$k] + $v;
}
}

Count the item from an array in PHP

How can I count in a multidimensional array the number of element with a special condition ?
Array
(
[0] => Array
(
[item] => 'Banana'
)
[1] => Array
(
[item] => 'Banana'
)
[2] => Array
(
[item] => 'Cherry'
)
[3] => Array
(
[item] => 'Apple'
)
)
For example, for this array I should find 2 for Banana.
Si I tried:
$i=0;
foreach($array as $arr) {
if($arr[item]=='Banana') { $i++; }
}
Is there a better solution please ?
Thanks.
Method 1:
Using built-in functions - array_column and array_count_values:
print_r(array_count_values(array_column($arr,'item')));
Method 2:
Using foreach with simple logic of making your fruit as key and its count as value:
$arr = [
["item"=>"Banana"],
["item"=>"Banana"],
["item"=>"Cherry"],
["item"=>"Apple"]
];
$countArr = [];
foreach ($arr as $value) {
$item = $value['item'];
if(array_key_exists($item, $countArr)) // If key exists, increment its value
$countArr[$item]++;
else // Otherwise, assign new key
$countArr[$item] = 1;
}
print_r($countArr);
Final result in both case would be:
Array
(
[Banana] => 2
[Cherry] => 1
[Apple] => 1
)
So when you want Banana's count, you can get it like this:
echo $countArr['Banana'];
Use array_count_values(), it is pretty straight forward:
foreach($array as $arr) {
$new[] = $arr['item'];
}
print_r(array_count_values($new));
On a side note, there isn't anything wrong with your approach, unless you want to count all values. Also on a side note, I think you'll find a foreach() will eek out a slightly faster time than array_column(), especially on a large array.

PHP - Find the difference / subtraction between the values of two arrays

I am getting values of two company stocks through a third party website using an API. These are output as two arrays e.g.
$companyA = array([0] => 100 [1] => 100.20 [2] => 103.20);
$companyB = array([0] => 99 [1] => 101.30 [2] => 105.50);
Each key [0],[1],[2], etc.. represents a day and is the same day for both stock dates. I would like to try and find the difference in values in the array by doing a subtraction for each value. i.e. 100 - 99, 100.20-101.30, 103.20 - 105.50, etc...
I tried array_diff but it's not working.
Thank you.
You can use array_map
$result = array_map(function ($firstElement, $secondElement) {
return $firstElement - $secondElement;
}, $companyA, $companyB);
You can also try this with basics:
<?
$companyA = array(100,100.20,103.20);
$companyB = array(99,101.30,105.50);
$newArr = array();
foreach ($companyA as $key => $value) {
$newArr[] = ($value-$companyB[$key]);
}
echo "<pre>";
print_r($newArr);
?>
Result:
Array
(
[0] => 1
[1] => -1.1
[2] => -2.3
)

Flatten 2D Array Into Separate Indexed Arrays

I have the array:
$total =array();
Array (
[0] => Array
(
[0] => 1
[1] => 3
)
[1] => Array
(
[0] => 6
[1] => 7
[2] => 8
)
[2] => Array
(
[0] => 9
[1] => 10
)
)
I need to dynamically change each array into an indexed array for a Cartesian function.
Here is how I need the code to look for the function to work correctly:
$count = cartesian(
Array(1,3),
Array(6,7,8),
Array(9,10)
);
Any help would be greatly appreciated! I have tried flattening, looping, using array_values, using just the array itself and I keep falling short.
Thanks
Nick
function cartesian() {
$_ = func_get_args();
if(count($_) == 0)
return array(array());
$a = array_shift($_);
$c = call_user_func_array(__FUNCTION__, $_);
$r = array();
foreach($a as $v)
foreach($c as $p)
$r[] = array_merge(array($v), $p);
return $r;
}
$count = call_user_func('cartesian', array($total));
print_r($count);
Your arrays already look exactly the way you want them to. array(1,3) is the same as array(0 => 1, 1 => 3) and both are an array with the value 1 at key 0 and 3 at key 1. Exactly what the debug output shows you.
It seems you just need to pass them as separate arguments to the function. E.g.:
cartesian($total[0], $total[1], $total[2])
For dynamic lengths of arrays, do:
call_user_func_array('cartesian', $total)
I believe that your $total array is multi-dimensional array with numeric indexed. So yo can try like this
$count = cartesian($total[0], $total[1], $total[2]);

PHP Get the first value of all arrays in a multidimensional array [duplicate]

This question already has answers here:
Is there a function to extract a 'column' from an array in PHP?
(15 answers)
Closed 1 year ago.
Here's a section my multidimensional array:
Array (
[0] => Array ( [0] => Height [1] => 40 )
[1] => Array ( [0] => Weight [1] => 15 )
[2] => Array ( [0] => Ctr_Percent [1] => 15 )
)
What would the syntax be for just printing height, weight, and ctr_percent? I don't mean echoing it like:
echo $array[0][0];
echo $array[1][0];
Is there a way to iterate through the entire multidimensional array and echo out the first value of each child array?
Supposing you use php 5.3:
$first_elements = array_map(function($i) {
return $i[0];
}, $data);
Otherwise you need to implement a callback function or just use plain old foreach
Here is a one-liner:
array_map('array_shift', $array);
Will return:
Array
(
[0] => Height
[1] => Weight
[2] => Ctr_Percent
)
And here is another one:
array_combine(array_map('array_shift', $temp), array_map('array_pop', $temp))
Will return:
Array
(
[Height] => 40
[Weight] => 15
[Ctr_Percent] => 15
)
Use array_column:
$result = array_column($array, 0);
foreach ($main_array as $inner_array){
echo $inner_array[0] . "\n";
}
foreach($array as $x) {
echo $x[0]."\n";
}
I think the function your looking for is reset() e.g.
array_map('reset', $array);
or
foreach ($array as $subarray)
echo reset($subarray)."\n";
Note that this works even if 0 is not the first index of the array. E.g. $a = [1=>5,0=>3]; echo reset($a); would still echo 5;.
The easiest way to do it using array_walk
function getFirstElement(&$val){
$val = $val[0];
}
array_walk($data,'getFirstElement');
Now if you print $data like print_r($data); you will get result as below
Array
(
[0] => Height
[1] => Weight
[2] => Ctr_Percent
)

Categories