grouping multi-dimensional array in PHP - php

I have a multi-dimensional array, and I want to group it by org and then by dept. I have the first level of grouping working:
$groups = array();
foreach($inv_h as $item) {
$groups[$item['org']][] = $item;
}
How do I achieve the second level of grouping?

If I understand you correctly then it's as simple as repeating what you've already done for the second tier of the array:
$groups = array();
foreach($inv_h as $item) {
$groups[$item['org']][$item['dept']][] = $item;
}
That should give you an array that looks like this:
groups = array(
org1 => array(
dept1 => array(results...),
dept2 => array(results...)
),
org2 => array(
dept3 => array(results...),
dept4 => array(results...)
)
)

Related

get me the value of multi dimensional php array with subarrays

I have this array:
static $countryList = array(
["AF" => "Afghanistan"],
["AL" => "Albania"],
["DZ" => "Algeria"],
//many more countries
);
I want to do something like $countryList['DZ'] to get "Algeria"
why those damned sub arrays?
well, some countries must come twice
basically this...
static $countryList = array(
["US" => "USA"],
["AL" => "Albania"],
["DZ" => "Algeria"],
//...
["UB" => "Uganda"],
["US" => "USA"]
);
it's used for a select list
Make another array that's an associative array:
$countryMap = [];
foreach ($countryList as $country) {
foreach ($country as $short => $long) {
$countryMap[$short] = $long;
}
}
Then you can use $countryMap["DZ"]

Add values in second array depending upon the values in first array

Here's the situation:
Suppose I have first Array as:
Array(
[0] => Person1
[1] => Person1
[2] => Person2
)
And second array as:
Array(
[0] => 100.00
[1] => 150.25
[2] => 157.15
)
How do I add values (100.00 + 150.25) of second Array and merge them (250.25) so that they belong to Person1 in the first array.
Desired Output:
Array(
[0] => 250.25 // for Person1 in the first Array after adding
[1] => 157.15 // for Person2 in the first Array
)
Any help is highly appreciated. Thank You.
P.S.: All the values are coming from the database.
EDIT 1:
Here's what I have tried, but this outputs the second array as it is:
$sums = array();
$sums = array_fill_keys(array_keys($affiCode + $affiCommAmount), 0);
array_walk($sums, function (&$value, $key, $arrs) {
$value = #($arrs[0][$key] + $arrs[1][$key]);
}, array($affiCode, $affiCommAmount)
);
The arrays are the same size, so you can use a for loop to process them simultaneously:
for($i = 0; $i<count($personArray); $i++)
Within the loop, construct a new array keyed to the values from the first array. If the key does not yet exist, initialize it:
if (!isset($newArray[$personArray[$i]])) {
$newArray[$personArray[$i]] = 0.0;
}
then add the new value to the selected array key:
$newArray[$personArray[$i]] += $valueArray[$i]
When the loop ends, $newArray will look like:
Array(
['Person1'] => 250.25
['Person2'] => 157.15
)
If you want to replace the 'Person1' and 'Person2' keys with numerical indexes, use array_values():
$numericallyIndexedArray = array_values($newArray);
The final code looks like:
$newArray = [];
for($i = 0; $i<count($personArray); $i++) {
if (!isset($newArray[$personArray[$i]])) {
$newArray[$personArray[$i]] = 0;
}
$newArray[$personArray[$i]] += $valueArray[$i];
}
// Optionally return the new array with numerical indexes:
$numericallyIndexedArray = array_values($newArray);
Get the person from first array by index and add the money:
for($i=0;$i<count(arrayPerson);$i++){
$arrayPerson[$i]->addMoney($arrayMoney[$i])
//Or $arrayPerson[$i]->Money += $arrayMoney[$i]
} //$i defines your index in the array.
sql
Better though to make a join in the SQL and sum the money and group by PersonID.
for example:
SELECT person.* COUNT(Money) FROM Person
LEFT JOIN Money
ON person.ID = Money.PersonID
GROUP BY person.ID
Simple foreach loop:
$people = array('Person1', 'Person1', 'Person2');
$values = array(100.00, 150.25, 157.15);
$output = array();
foreach ($people as $key => $person) {
if (! isset($output[$person])) {
$output[$person] = 0;
}
if (! empty($values[$key])) {
$output[$person] += $values[$key];
}
}
// $output = array(2) { ["Person1"]=> float(250.25) ["Person2"]=> float(157.15) }
If you want to do away with the keys in $output, you can use array_values($output)
Here's an example

Sorting an unordered array and make it into multidimensional with alphabetical keys?

I have a form where you type in different movies and separate them with "|". The database currently contains:
Spider-man|Spider-man 2|Spider-man 3|Apple|Google|Banana|Citrus
I have done an explode() of this text string so each title goes into an array:
$collection = explode('|', $collection);
For the sake of keeping things sorted alphabetically, I did this:
array_multisort($collection);
So far it's alright. However, now I need to make this array multidimensional with each key corresponding the letter the values start with. It should become like this:
Array(
[A] => Array(
'Apple'
)
[B] => Array(
'Banana'
)
[C] => Array(
'Citrus'
)
[G] => Array(
'Google'
)
[S] => Array(
'Spider-man',
'Spider-man 2',
'Spider-man 3'
)
)
How can I achieve this?
Thanks in advance,
Filip
There is no built-in function for that. You need to craft something on your own. Like this:
$string = 'Spider-man|Spider-man 2|Spider-man 3|Apple|Google|Banana|Citrus';
$result = array();
foreach(explode('|', $string) as $item) {
$firstLetter = $item[0];
if(!isset($result[$firstLetter])) {
$result[$firstLetter] = array();
}
$result[$firstLetter][] = $item;
}
ksort($result);
var_dump($result);
Not the way you should be storing things in the database. You should have a table that relates to that one that holds the movies each in its own row. That being said:
//array_multisort($collection); // don't need this
sort($collection);
foreach($collection as $movie) {
$result[$movie[0]][] = $movie;
}
If there might be some movies that start with a lowercase letter, then:
foreach($collection as $movie) {
$result[strtoupper($movie[0])][] = $movie;
}
ksort($result);
$input = 'Spider-man|Spider-man 2|Spider-man 3|Apple|Google|Banana|Citrus';
$collection = array();
$movies = explode('|', $input);
sort($movies);
foreach ($movies as $movie) {
$collection[strtoupper($movie[0])][] = $movie;
}
print_r($collection);

PHP How to push array into array[key]?

This is the code I have:
$orders = Array();
foreach ($unassigned as $uorder) {
$array = Array(
"ordid" => $uorder->idord,
"fecha" => $uorder->datorod,
"cliente" => $uorder->idcli
);
array_push($orders[$uorder->user_id], $array);
}
print_r($orders);
Which results:
Array (
[vendor1] =>
[vendor2] =>
)
I want to make some kind of sort
So I could use $orders[vendor1][0][ordid] to find the first order that the vendor made.
You have to assign $orders[$uorder->user_id] as an array first, otherwise it doesn't make sense to push an item onto it. Additionally, you can use the shorthand append notation:
if(!isset($orders[$uorder->user_id]))
$orders[$uorder->user_id] = array();
$orders[$uorder->user_id][] = $array;
In your foreach loop check if $orders[$uorder->user_id] is an array, if not create one.
foreach($unassigned as $uorder):
if(! is_array($orders[$uorder->user_id]))
$orders[$uorder->user_id] = array();
array_push($orders[$uorder->user_id],Array("ordid" => $uorder->idord, "fecha" => $uorder->datorod, "cliente" => $uorder->idcli));
endforeach;

What's wrong with this php foreach code? (merged array)

$db = new PDO("mysql:host=$hostname;dbname=$database", $username, $password);
$items = 'SELECT items FROM menus';
$itemLink = 'SELECT itemLink FROM menus';
$itemQuery = $db->query($items);
$linkQuery = $db->query($itemLink);
$fetchItem = $itemQuery->fetch(PDO::FETCH_ASSOC);
$fetchLink = $linkQuery->fetch(PDO::FETCH_ASSOC);
$merged = array_merge($fetchItem,$fetchLink);
foreach($merged as $key=>$value){
echo "${key} => ${value} <br />";
}
This is what it looks like in the database:
items |itemLink
----------------------
Kill Bill|Kill Bill link
Preman |Preman link
So, the expected output, or at least what I thought must be this:
items => Kill Bill
items => Preman
itemLink => Kill Bill Link
itemLink => Preman Link
But the resulted output from the code is this:
items => Kill Bill
itemLink => Kill Bill Link
It's missing the other items and itemLink
So, how do I achieve the output that I want?
$fetchItem = $itemQuery->fetch(PDO::FETCH_ASSOC);
$fetchLink = $linkQuery->fetch(PDO::FETCH_ASSOC);
This only fetches the first row of each resultset. You need fetchAll:
$fetchItem = $itemQuery->fetchAll(PDO::FETCH_ASSOC);
$fetchLink = $linkQuery->fetchAll(PDO::FETCH_ASSOC);
and adjust the rest of your code.
foreach($merged as $entry) {
foreach( $entry as $key => $value ) {
echo "${key} => ${value} <br />";
}
}
EDIT:
The call of fetch only retrieved the first row of the resultset, whereas fetchAll parses the complete resultset into an Array. So the Objects look like this afterwards:
Array(
[0] => { 'items' => 'Kill Bill' },
[1] => { 'items' => 'Preman' }
)
Array(
[0] => { 'itemLink' => 'Kill Bill' },
[1] => { 'itemLink' => 'Preman' }
)
array_merge concatenate both arrays to the following:
Array(
[0] => { 'items' => 'Kill Bill' },
[1] => { 'items' => 'Preman' },
[2] => { 'itemLink' => 'Kill Bill' },
[3] => { 'itemLink' => 'Preman' }
)
So we now have a two dimensional array. To traverse the values we need first to select each $entry, which is done in the outer foreach and can afterwards access the key/value structure in the inner foreach.
As pointed out in the other comment: If you want to preserve the connection between itemsand itemLink, you should change the query in the first place to
SELECT items, itemLink FROM menus
You can use simple array_combine() function to do what you are trying to do now.
$merged = array_combine($fetchItem, $fetchLink);
This will make all the item from $fetchItem as keys to the item from $fetchLink.

Categories