Combine and sum values in multi-dimensional associative array using php - php

I have an associative array that looks like this:
Array (
[0] => Array (
[amount] => 3
[name] => Chuck
)
[1] => Array (
[amount] => 2
[name] => Steve
)
[2] => Array (
[amount] => 5
[name] =>
)
[3] => Array (
[amount] => 4
[name] => Chuck
)
[4] => Array (
[amount] =>
[name] => Chuck
)
)
I need to remove values that are missing a name or amount e.g. [2] and [4] and then sum the totals for each name so that the final array is:
Array (
[0] => Array (
[amount] => 7
[name] => Chuck
)
[1] => Array (
[amount] => 2
[name] => Steve
)
)

For anyone looking for this nowadays, this would be much cleaner:
$sum = array_sum(array_column($data, 'amount'));

Try this:
$starting_array = array( ... ); // Initial array with your setup
$final_array = array();
$sum = 0;
foreach ($starting_array as $idx => $data) {
if (!empty($data['amount']) && !empty($data['name'])) {
$final_array[$idx] = $data;
$sum += $data['amount'];
}
}
// After looping through all of the items, $final_array should contain all
// of the specific items that have an amount and name set. In addition, the
// total of all of the amounts will be in $sum.
Take a look at php's empty(). Note: If 0 is an allowed value, you may want to use is_null() instead.

Related

How to merge three arrays according to common key in php

I have three arrays first array include ids and employees name and second array have monthly collection with employee ids and third array have daily collection with employee id and daily collection I want to merge these array with ids and name and dcollection and monthly collection but the desired output is not coming here my first array $ids is
Array
(
[0] => stdClass Object
(
[id] => 1
[name] => Rohit
)
[1] => stdClass Object
(
[id] => 2
[name] => Emop1
)
[2] => stdClass Object
(
[id] => 3
[name] => Pankaj
)
[3] => stdClass Object
(
[id] => 4
[name] => tejpal singh
)
)
second array $q1 is
Array
(
[0] => stdClass Object
(
[name] => Rohit
[id] => 1
[mcollecton] => 100
)
[1] => stdClass Object
(
[name] => Emop1
[id] => 2
[mcollecton] => 1222
)
)
third array $q2 is
Array
(
[0] => stdClass Object
(
[name] => Rohit
[id] => 1
[dcollecton] => 300
)
[1] => stdClass Object
(
[name] => Emop1
[id] => 2
[dcollecton] => 150
)
)
so far what I have tried
$new_array = array();
foreach($ids as $k) {
$q1n = array("id"=>$k->id,"name"=>$k->name);
foreach($q1 as $k1) {
if($k->id==$k1->id){
$mc = array("mc"=>$k1->mcollecton);
array_merge($q1n,$mc);
}
}
foreach($q2 as $k1){
if($k->id==$k1->id){
$dc = array("dc"=>$k1->dcollecton);
array_merge($q1n,$dc);
}
}
$a = array_merge($q1n,$mc);
$av = array_merge($q1n,$dc);
array_push($new_array,$q1n);
}
but the output is coming as
Array
(
[0] => Array
(
[id] => 1
[name] => Rohit
)
[1] => Array
(
[id] => 2
[name] => Emop1
)
[2] => Array
(
[id] => 3
[name] => Pankaj
)
[3] => Array
(
[id] => 4
[name] => tejpal singh
)
)
I want the output be like
Array
(
[0] => Array
(
[id] => 1
[name] => Rohit
[mcollection] => 100
[dcollection] => 300
)
[1] => Array
(
[id] => 2
[name] => Emop1
[mcollection] => 1222
[dcollection] => 150
)
[2] => Array
(
[id] => 3
[name] => Pankaj
[mcollection] => 0
[dcollection] => 0
)
[3] => Array
(
[id] => 4
[name] => tejpal singh
[mcollection] => 0
[dcollection] => 0
)
)
So I have tried many times but the desired output is not coming . please help me out how to get the desired output.
It seemed like that answer could be modified, or put in a function that you could call multiple times if needed to combine more than two arrays.
There's probably cleaner ways to handle this with array functions like array_merge or array_walk, but this is the general idea of how I might approach it. I haven't tested this, but maybe it's useful.
foreach($first as $key1 => $value){
foreach($second as $key2 => $value2){
// match the ids and check if array key exists on first array
if($value['id'] === $value2['id'] && empty($first[$key2])){
$first[$key][$key2] = $value2;
}
}
}
EDIT: Based on the answer you posted vs the question you asked, are you incrementing the collection numbers or just setting them? In other words why use +=? You should also be able to remove array_merge and array_push.
Below is geared more towards what you're trying to do. I haven't tested this either, but if you run into errors, post your code with the errors returned so that it's easier to debug:
foreach($ids as $k)
{
$thisArray = $newArray[] = array("id"=>$k->id,"name"=>$k->name);
foreach($q1 as $k1)
{
if($k->id == $k1->id && !empty($k1->mcollecton))
{
$thisArray['mc'] = $k1->mcollecton;
}
}
foreach($q2 as $k2)
{
if($k->id == $k2->id && !empty($k2->dcollecton))
{
$thisArray['dc'] = $k2->dcollecton;
}
}
}
// This should have both new collections fields on all array items
print_r($newArray)

PHP array - count unique IDs

I have a PHP array that looks like this
Array
(
[0] => Array
(
[events] => Array
(
[0] => Array
(
[label] => apple
[id] => 3
)
[1] => Array
(
[label] => onion
[id] => 3
)
[2] => Array
(
[label] => pear
[id] => 2
)
[3] => Array
(
[label] => orange
[id] => 1
)
[4] => Array
(
[label] => grape
[id] => 41
)
)
)
)
I am trying to get a total count of unique IDs, so in the example above I would want to get a count of 4
Do I need to loop through the array or is there a function that can do it more efficiently? Currently it is a small data set but it could grow fairly large.
You can use array_column to get all the IDs, and array_unique to remove the duplicates, then count that.
count(array_unique(array_column($array[0]['events'][0], 'id')))
One way or another you'll have to loop through it. I think most efficiently would be
function getUnique($arr){
$val = array();
foreach($arr[0]["events"] as $v){
$val[$v["id"]] = true;
}
return count($val);
}

Padding a multidimensional array with array_pad?

$summary=$query->result_array(); //where the original array is created
print_r($summary); //dump contents
Produces this:
Array ( [0] => Array ( [RecordID] => 2 [UserID] => 3 [BookID] => 1 [Title] => FirstBook ) [1] => Array ( [RecordID] => 3 [UserID] => 3 [BookID] => 2 [Title] => Sequel ) )
I would now like to pad the multi dimensional array with a price element so as to create the results of
Array ( [0] => Array ( [RecordID] => 2 [UserID] => 3 [BookID] => 1 [Title] => FirstBook [Price] => 99 ) [1] => Array ( [RecordID] => 3 [UserID] => 3 [BookID] => 2 [Title] => Sequel [Price] => 99) )
The only way I can think of doing this is to break the multidimensional array into one-dimensional arrays, modify them, and then re-assemble them. Doesn't sound terribly efficient though. Any suggestions?
You can update the internal arrays by reference, note the & here:
foreach($summary as &$details){
$details['Price'] = $price; // wherever $price comes from...
}
try to use:
foreach ($summary as $idx => &$arrValue)
$arrValue['Price'] = ###;
If you're fixed on your dimensions, iterate with a reference and modify $summary in place...
<?php
foreach ($summary as &item) {
$item['price'] = 99;
}
If you have particular objections/issues with references:
<?php
foreach ($summary as $key=>item) {
$summary[$key]['price'] = 99;
}

Naming Keys in a Multidimensional Array in PHP

I have data from a csv file that I organized into a multidimensional array using the following method:
$handle = fopen("bankdata.csv", "r");
while(($data = fgetcsv($handle, 0 ,",")) !==FALSE) {
$transactions[] = $data;
}
The array now looks something like this:
Array
(
[0] => Array
(
[0] => 2000
[1] => paycheck
[2] => credit
)
[1] => Array
(
[0] => 75
[1] => grocery
[2] => debit
)
[2] => Array
(
[0] => 45
[1] => gas
[2] => debit
)
[3] => Array
(
[0] => 900
[1] => investments
[2] => credit
)
[4] => Array
(
[0] => 1500
[1] => bonus
[2] => credit
)
Now I would like to name the keys in each nested array. I thought I would create a new multidimensional array with an equal amount of nested arrays, their values being the intended name of the keys I would like to add to the original array, then do 'array_combine':
$names = array('amount','source','type');
$run = 1;
while($run < 6){
$run = $run +1;
$names2[] = $names;
}
$combine = array_combine($names2, $transactions);
You could use array combine:
$keynames=array('amount','source','type');
foreach ($transactions as $i=>$row) {
$transactions[$i]=>array_combine($keynames, $row);
}
The right way to solve the problem is not to read the the data into an array then transform it - transform it as you read it.
while(($data = fgetcsv($handle, 0 ,",")) !==FALSE) {
$transactions[]=array_combine($keynames, $data);
}
BTW PHP doesn't do multi-dimensional arrays - they're nested. Despite what it says in the manual, they only emulate multi-dimensional arrays.
Try the following:
$arr = array(
array(2000, 'paycheck', 'credit'),
array(75, 'grocery', 'debit'),
array(45, 'gas', 'debit'),
array(900, 'investments', 'credit'),
array(1500, 'bonus', 'credit')
);
$keys = array('amount','source','type');
// $a will make a reference to the array within $arr
// and override the array
foreach($arr as &$a)
{
// Override the array keys
$a = array_combine($keys, $a);
}
/* Output:
Array
(
[0] => Array
(
[amount] => 2000
[source] => paycheck
[type] => credit
)
[1] => Array
(
[amount] => 75
[source] => grocery
[type] => debit
)
[2] => Array
(
[amount] => 45
[source] => gas
[type] => debit
)
[3] => Array
(
[amount] => 900
[source] => investments
[type] => credit
)
[4] => Array
(
[amount] => 1500
[source] => bonus
[type] => credit
)
)
*/

Comparing&editing two tabdelimeted files with PHP?

I want to compare two tabdelimeted files. I take the files and converts them into two arrays with the following structure:
Array 1
Array
(
[0] => Array
(
[name] => name1
[qty] => 200
)
[1] => Array
(
[name] => name2
[qty] => 9
)
[2] => Array
(
[name] => name3
[qty] => 3
)
[3] => Array
(
[name] => name4
[qty] => 1
)
)
Array 2
Array
(
[0] => Array
(
[name] => name1
[qty] => 180
)
[1] => Array
(
[name] => name2
[qty] => 9
)
)
How can I compare these two arrays and where the value is different to replace the value in the array 2 with array of value 1.
The easiest way to do this would be to create an associative array for the second set of data, instead of the array format you has used above. Since you only seem to have two "columns", and these are effectively a key/value relationship this should be nice and easy.
This example takes the two input arrays you have generated to do it, but you can probably adjust this so that you create the associative array directly as you read the second:
// first create an associative array from the second indexed array
$secondAssoc = array();
foreach ($secondArray as $row) {
$secondAssoc[$row['name']] = $row['qty'];
}
/*
$secondAssoc now looks like:
Array
(
[name1] => 180
[name2] => 9
)
*/
// Now loop the first array and update it
foreach ($firstArray as $rowId => $row) {
if (isset($secondAssoc[$row['name']]) && $secondAssoc[$row['name']] != $row['qty']) {
$firstArray[$rowId]['qty'] = $secondAssoc[$row['name']];
}
}
/*
$firstArray now looks like this:
Array
(
[0] => Array
(
[name] => name1
[qty] => 180
)
[1] => Array
(
[name] => name2
[qty] => 9
)
[2] => Array
(
[name] => name3
[qty] => 3
)
[3] => Array
(
[name] => name4
[qty] => 1
)
)
*/
See it working.
EDIT Here is a version that also creates an array, $modifiedItems, that holds only the items that have changed:
// first create an associative array from the second indexed array
$secondAssoc = array();
foreach ($secondArray as $row) {
$secondAssoc[$row['name']] = $row['qty'];
}
// Now loop the first array and update it
$modifiedItems = array();
foreach ($firstArray as $rowId => $row) {
if (isset($secondAssoc[$row['name']]) && $secondAssoc[$row['name']] != $row['qty']) {
$firstArray[$rowId]['qty'] = $secondAssoc[$row['name']];
$modifiedItems[] = array('name'=>$row['name'],'qty'=>$secondAssoc[$row['name']]);
}
}
See it working.

Categories