Sorting Adjacency List Children Alphabetically - php

If I have an adjacency list sorted by id/parent_id, is there an easy way to sort all of a parent's children alphabetically by a third text field (say "name")?
I have used information provided here: http://explainextended.com/2009/03/17/hierarchical-queries-in-mysql/ to get MySQL to return the sorted adjacency list. Ideally this would allow me to sort the children by a third column, but the test data set does not include extra columns at all in that example.
My data looks like this after I query for it but it needs to be sorted by the descendants, alphabetically.
$myArr[] = array(1,0,"instruments");
$myArr[] = array(2,1,"electric");
$myArr[] = array(3,1,"acoustic");
$myArr[] = array(4,2,"guitar");
$myArr[] = array(5,2,"banjo");
$myArr[] = array(6,3,"guitar");
$myArr[] = array(5,3,"banjo");
Or:
array (
0 =>
array (
0 => 1,
1 => 0,
2 => 'instruments',
),
1 =>
array (
0 => 2,
1 => 1,
2 => 'electric',
),
2 =>
array (
0 => 3,
1 => 1,
2 => 'acoustic',
),
3 =>
array (
0 => 4,
1 => 2,
2 => 'guitar',
),
4 =>
array (
0 => 5,
1 => 2,
2 => 'banjo',
),
5 =>
array (
0 => 6,
1 => 3,
2 => 'guitar',
),
6 =>
array (
0 => 5,
1 => 3,
2 => 'banjo',
),
)
I need this to be sorted like so:
instruments
acoustic
banjo
guitar
electric
banjo
guitar
Thanks!

I don't know what exactly you want to do given that you have no code example, but isn't it easier to do like this:
SELECT * FROM my_table ORDER BY id, parent_id, title;
that orders first by id, then by parent_id when ids are the same and for title if ids and parent_ids are the same

Related

PHP associative array with non-unique keys

Struggling with concept of an associative array that maps userIDs to partIDs and re-order quantity for the part.
We have bunch of parts that I need to re-order, but I must keep track of which user needs what parts re-purchased for them. The list of UserIDs comes from one table, then the inventory_used comes from another table.
Suppose a list like this:
Example One:
UserID PartID Qty_Used
1 3 2
1 4 7
2 1 4
2 4 3
3 3 5
After creating an array with the above information, I must create a re-order form (table) for the parts. Therefore, ignoring the userID, group them by the partID, and sum up the total Qty (per part). The re-order table should look something like this:
Example Two:
PartID Qty_to_Reorder
1 4
3 7
4 10
I know I'm going to take a ton of downvotes for failing to show code, but I can't wrap my mind around this seemingly simple problem. (This is for my office, not a school project).
How do I:
(1) Structure the first array (what would the loop to create it look like?), and then
(2) Loop through that array to summarize/group partIDs => Qty for re-order report, as per 2nd example above?
For the first loop, i was thinking of something like this:
Loop through UserIDs {
Loop through PartIDs {
$arrReorder[UserID][PartID] = Qty_Used;
}
}
Is that correct? How would I loop through $arrReorder to sum-up the qty used for each partID, and get the re-order report (example 2)?
SELECT SUM(Qty_Used) AS total FROM mytable WHERE PartID=3
PS: Using PHP
<?php
$data = array();
$data[] = array("UserID" => 1, "PartID" => 3, "Qty_Used" => 2);
$data[] = array("UserID" => 1, "PartID" => 4, "Qty_Used" => 7);
$data[] = array("UserID" => 2, "PartID" => 1, "Qty_Used" => 4);
$data[] = array("UserID" => 2, "PartID" => 4, "Qty_Used" => 3);
$data[] = array("UserID" => 3, "PartID" => 3, "Qty_Used" => 5);
$PartID = 3;
$sum = 0;
foreach ($data as $arr) {
if ($arr['PartID'] == $PartID)
$sum += $arr['Qty_Used'];
}
echo $PartID."\t".$sum."\r\n";
?>
Arrays have a key and value where the value can be another array. Determine what is the key value.
I am assuming you have users consuming parts and you have to re-order the parts from your supplier. No where the user is a customer and the user has a auto re-order policy.
What triggers a reorder? If re-order quantity is 10 and user uses 1, there should be nine in stock.
Create the partsUsed array elements, This is a bit tricky:
$partsUsed[$part][] = array($qtyUsed,$user);
The reason the empty brackets [] is there is to allow duplicate part numbers in the parts used, and still key part as the key.
The value is an array to key the association between user and parts.
what you end up with is a sequentially numbered secondary key where the value is just a throw away, but allows duplicate part numbers.
$partsUsed[3][] = array(2,1);
$partsUsed[4][] = array(7,1);
$partsUsed[1][] = array(4,2);
$partsUsed[4][] = array(3,2);
$partsUsed[3][] = array(5,5);
ksort($partsUsed); // sorts key on part number
var_export($partsUsed);
Result array (var_export):
array (
1 =>
array (
0 =>
array (
0 => 4,
1 => 2,
),
),
3 =>
array (
0 =>
array (
0 => 2,
1 => 1,
),
1 =>
array (
0 => 5,
1 => 5,
),
),
4 =>
array (
0 =>
array (
0 => 7,
1 => 1,
),
1 =>
array (
0 => 3,
1 => 2,
),
),
)
Notice part 3 and 4 have two arrays.
$reorder[1] = 4 ;
$reorder[2] = 7 ;
$reorder[4] = 10 ;
var_export($reorder);
Result array:
array (
1 => 4,
2 => 7,
4 => 10,
)
Now not sure how to determine what gets reordered and how many.
I'll show how to get the values:
foreach($partsUsed as $part => $value){
foreach($value as $k => $v){
echo "Part $part: Qty:$v[0] User:$v[1]\n";
$qtyUsed[$part] += $v[1];
}
}
var_export($qtyUsed);
Outputs:
Part 1: Qty:4 User:2
Part 3: Qty:2 User:1
Part 3: Qty:5 User:3
Part 4: Qty:7 User:1
Part 4: Qty:3 User:2
$qtyUsed
array (
1 => 2,
3 => 4,
4 => 3,
)
foreach ($qtyUsed as $part => $qty){
$order[$part] = $reorder[$part];
}
var_export($order);
Result $order:
array (
1 => 4,
3 => 7,
4 => 10,
)

PHP foreach not behaving as expected

I have an array (POSTed from a Python application) called "observations". It looks like this:
Array
(
[0] => Array
(
['remote_id'] => 1
['dimension_id'] => 1
['metric'] => 1
)
[1] => Array
(
['remote_id'] => 1
['dimension'] => 2
['metric'] => 2
)
[2] => Array
(
['remote_id'] => 1
['dimension_id'] => 3
['metric'] => 3
)
(etc)
I want to iterate through all those instances of remote_id, dimension_id and metric and write them to a database. But I can't access them - here's my PHP:
foreach ($_POST["observations"] as $observation) {
echo "Let's try and access the whole array... \n";
print_r ($observation);
echo "But what about the sub elements? \n";
print_r ($observation[0]);
print_r ($observation['dimension_id']);
}
This returns:
Let's try and access the whole array...
Array
(
['remote_id'] => 1
['dimension_id'] => 1
['metric'] => 1
)
But what about the sub elements?
Let's try and access the whole array...
Array
(
['remote_id'] => 1
['dimension'] => 2
['metric'] => 2
)
But what about the sub elements?
(etc)
So my print_r ($observation[0]) and print_r ($observation['dimension_id']) are both failing to access the appropriate sub-elements and returning empty. What am I missing here?
Edit: a few questions about my (potentially malformed) POST. Doing it in Python like so:
data = urllib.urlencode([
("observations[0]['remote_id']", 1),
("observations[0]['dimension_id']", 1),
("observations[0]['metric']",metric1),
("observations[1]['remote_id']", 1),
("observations[1]['dimension']", 2),
("observations[1]['metric']", metric2),
("observations[2]['remote_id']", 1),
("observations[2]['dimension_id']", 3),
("observations[2]['metric']",metric3),
("observations[3]['remote_id']", 1),
("observations[3]['dimension_id']", 4),
("observations[3]['metric']",metric4),
("observations[4]['remote_id']", 1),
("observations[4]['dimension_id']", 5),
("observations[4]['metric']",metric5),
])
response = urllib2.urlopen(url=url, data=data)
This works according to your given array:
$array = Array(
0 => Array
(
'remote_id' => 1,
'dimension_id' => 1,
'metric' => 1
),
1 => Array
(
'remote_id' => 1,
'dimension_id' => 2,
'metric' => 2
),
2 => Array
(
'remote_id' => 1,
'dimension_id' => 3,
'metric' => 3
)
);
foreach ($array as $observation) {
echo "Remote id: ". $observation['remote_id']."<br />";
echo "Dimension id: ". $observation['remote_id']."<br />";
echo "Metric: ". $observation['metric']."<br />";
}
That will print:
Remote id: 1
Dimension id: 1
Metric: 1
Remote id: 1
Dimension id: 1
Metric: 2
Remote id: 1
Dimension id: 1
Metric: 3
But it looks like your $_POST["observations"] is not an array of $observation's but just one $observation.
There is probably something wrong in your form. Did you use arrays in your input like
<input type="text" name="observations[0]['metric']" />?

Sort PHP array by numerical values

I would like to sort the following names
Array ( [Jessie] => 2 [Sarah] => 3 [Simon] => 2 [John] => 2 [Kevin] => 1 [Canvasser] => 8 [canvasser] => 11 )
based on the values corresponding to them
I printed the names through the following function
// get canvasser individual names and count houses canvassed
foreach ($canvassers as $key => $value) {
// Add to the current group count if it exists
if ( isset( $canvasser_counts[$value] ) ) {
$canvasser_counts[$value]++;
}
// or initialize to 1 if it doesn't exist
else {
$canvasser_counts[$value] = 1;
}
}
print_r($canvasser_counts);
where $canvassers simply held all the names eg.
$canvassers = array('Jessie', 'Simon', 'Jessie')
Any help would be really appreciated, I have spent so long on this but can't get my head straight to sort the array correctly.
You want to use asort() - http://php.net/manual/en/function.asort.php - to sort the values in ascending order, or arsort() - http://php.net/manual/en/function.arsort.php - to sort in descending order.
Given this PHP:
$vals = array("Jessie" => 2, "Sara" => 3, "Simon" => 2, "John" => 2, "Kevin" => 1, "Canvasser" => 8, "canvasser" => 11 );
print_r($vals); // current order
asort($vals); // sort array
print_r($vals); // new order
You will get the following output:
Array
(
[Jessie] => 2
[Sara] => 3
[Simon] => 2
[John] => 2
[Kevin] => 1
[Canvasser] => 8
[canvasser] => 11
)
Array
(
[Kevin] => 1
[Jessie] => 2
[John] => 2
[Simon] => 2
[Sara] => 3
[Canvasser] => 8
[canvasser] => 11
)

PHP merging arrays based on specific array key

I have 2 arrays that I want to merge based on a key's value in array 1. In the below example, I want the game_modes put into the games_list based on a key (id) in games_list.
Array 1 which is pulled from a table full of games:
$games_list = array(
0 => array(
'id' => 23,
'name' => 'Call of Duty: Modern Warfare 3'
),
2 => array(
'id' => 1,
'name' => 'Call of Duty: Black Ops'
)
);
Array 2 which is pulled from a table full of game modes:
$game_modes = array(
0 => array(
'id' => 1,
'game_id' => 1,
'description' => 'Capture the Flag'
),
1 => array(
'id' => 2,
'game_id' => 1,
'description => 'Domination'
),
2 => array(
'id' => 3,
'game_id' => 23,
'description' => 'Kill Confirmed'
)
);
I would like the result to be:
$games_list = array(
0 => array(
'id' => 23,
'name' => 'Call of Duty: Modern Warfare 3'
'modes' => array(
array(
'id' => 3,
'game_id' => 23,
'description' => 'Kill Confirmed'
)
)
),
2 => array(
'id' => 1,
'name' => 'Call of Duty: Black Ops'
'modes'=> array(
0 => array(
'id' => 1,
'game_id' => 1,
'description' => 'Capture the Flag'
),
1 => array(
'id' => 2,
'game_id' => 1,
'description => 'Domination'
)
)
)
);
Additional info, the site I'm working on currently has 71 games in its database and each game could have some arbitrary number of game modes.
Now, I could easily do a bunch of for loops and avoid this question all together. As of right now I don't have ton of game modes entered into the database but I keep adding more all the time. Over time doing exponentially more loops all the time will eventually make the page load speed come to a crawl.
I have taken the time to place this data into memcache to make future calls quicker avoiding the loop.
I've never been good with array_map as I don't quite understand how it works or if its even the right route.
Don't you think query level solution would be better?
The lengthy way would be:
// array: $game_modes;
// array: $game_lists;
foreach ($game_modes as $gm=>$modes){
if (isset($modes['game_id'])){
foreach ($game_lists as $gl=>$lists){
if ($lists['id'] == $modes['game_id']){
$game_lists[$gl]['modes'][] = $modes;
//break;
}
}
}
}
Output Category : Summary
$query = 'SELECT
g.id, g.name_name,
group_concat(gm.description) as descriptions
FROM games as g
LEFT JOIN games_modes as gm
ON g.id = gm.game_id
GROUP BY g.id';
Result:
id | name | descriptions
------------------------------------------------------------
1 | Call of Duty: Black Ops | Capture the Flag, Domination
Output Category : Detail
$query = 'SELECT
g.id, g.name_name,
gm.id, gm.description
FROM games as g
LEFT JOIN games_modes as gm
ON g.id = gm.game_id
ORDER BY g.id';
Result:
id | name | id | description
----- --------------------------- ------- ------------------
1 | Call of Duty: Black Ops | 1 | Capture the Flag
1 | Call of Duty: Black Ops | 2 | Domination
Try this to decrease looping
$cachearray = array();
foreach ($game_modes as $gm=>$modes){
if(array_key_exists($modes['game_id'],$cachearray))
{
$cachearray[$modes['game_id']]['modes'][] = $modes;
}
else
foreach ($games_list as $gl=>$lists){
if ($lists['id'] == $modes['game_id']){
$games_list[$gl]['modes'][] = $modes;
$cachearray[$lists['id']] = &$games_list[$gl];
break;
}
}
}
print_r($games_list);
It will be easier if you have $games_list array like this
$games_list = array(
23 => array(
'id' => 23,
'name' => 'Call of Duty: Modern Warfare 3'
),
1 => array(
'id' => 1,
'name' => 'Call of Duty: Black Ops'
)
);
And will more powerfull by using query
If you want to user array map, this code should be possible:
$ids = array_map(function($game) { return $game['id']; }, $games_list);
$id_mapping = array_flip($ids);
foreach($game_modes as $mode) {
if (array_key_exists($mode['game_id'], $id_mapping)) {
$games_list[$id_mapping[$mode['game_id']]]['modes'][] = $mode;
}
}
But I do not know whether this is faster than the two for loops.
try this:
$mode_map = array();
foreach($game_modes as $mode)
{
$game_id = $mode['game_id'];
if(!isset($mode_map[$game_id]))
{
$mode_map[$game_id] = array();
}
$mode_map[$game_id][] = $mode;
}
foreach($games_list as &$game)
{
$game_id = $game['id'];
if(isset($mode_map[$game_id]))
{
$game['modes'] = $mode_map[$game_id];
}
}
print_r($games_list);
result:
Array
(
[0] => Array
(
[id] => 23
[name] => Call of Duty: Modern Warfare 3
[modes] => Array
(
[0] => Array
(
[id] => 3
[game_id] => 23
[description] => Kill Confirmed
)
)
)
[2] => Array
(
[id] => 1
[name] => Call of Duty: Black Ops
[modes] => Array
(
[0] => Array
(
[id] => 1
[game_id] => 1
[description] => Capture the Flag
)
[1] => Array
(
[id] => 2
[game_id] => 1
[description] => Domination
)
)
)
)

PHP split array based on search results

I have a multidimensional array which is created by a MySQL query which collects results based on a number of groups and sums. The array is below.
I'm interested in the costtotal and hitcount for each type of 'ad_type', 'click_status' and 'link_status' variation.
The possible values of the 3 types of variable are known:
i.e.
ad_type 0 / 1
click_status 2 / 3
link_status 1 / 2
I would like to create a new array based on the results of each combination.
I'm guessing a search or split would do it but I'm not having much luck.
How would I go about doing this?
Array
(
[0.261346210037681] => Array
(
[costtotal] => 0.0015
[hitcount] => 1
[ad_type] => 0
[click_status] => 2
[link_status] => 1
)
[0.190427019438173] => Array
(
[costtotal] => 0.001
[hitcount] => 1
[ad_type] => 0
[click_status] => 3
[link_status] => 1
)
[0.563596305962276] => Array
(
[costtotal] => 0.007
[hitcount] => 5
[ad_type] => 1
[click_status] => 2
[link_status] => 1
)
[0.893211513658251] => Array
(
[costtotal] => 0
[hitcount] => 3
[ad_type] => 1
[click_status] => 2
[link_status] => 2
)
[0.209184847035617] => Array
(
[costtotal] => 0.004
[hitcount] => 2
[ad_type] => 1
[click_status] => 3
[link_status] => 1
)
[0.73545002260753] => Array
(
[costtotal] => 0
[hitcount] => 1
[ad_type] => 1
[click_status] => 3
[link_status] => 2
)
)
If I fully understand what you want, then this code should satisfy you:
function generateClickCounterInfo() {
return array(
'costTotal' => 0.0,
'hitCount' => 0
);
}
function generateLinkStatusStructure() {
return array(
1 => generateClickCounterInfo(),
2 => generateClickCounterInfo()
);
}
function generateClickStatusStructure() {
return array(
2 => generateLinkStatusStructure(),
3 => generateLinkStatusStructure()
);
}
function generateAdTypeArrayStructure() {
return array(
0 => generateClickStatusStructure(),
1 => generateClickStatusStructure()
);
}
function getClickCounterReport(array $data) {
$result = generateAdTypeArrayStructure();
foreach ($data as $key => $value) {
$adType = $value['ad_type'];
$clickStatus = $value['click_status'];
$linkStatus = $value['link_status'];
if (!isset($result[$adType])
|| !isset($result[$adType][$clickStatus])
|| !isset($result[$adType][$clickStatus][$linkStatus])) {
throw new Exception(
"Input data does not conform to expected format. " .
"ad_type = {$adType}, click_status = {$clickStatus}, link_status = ${linkStatus}"
);
}
$costTotal = $value['costtotal'];
$hitCount = $value['hitcount'];
$result[$adType][$clickStatus][$linkStatus]['costTotal'] += $costTotal;
$result[$adType][$clickStatus][$linkStatus]['hitCount'] += $hitCount;
}
return $result;
}
And than getClickCounterReport($data) (where $data is data provided by you) will produce following array: http://pastebin.ubuntu.com/607464/
P.S. Knowing disadvantages:
No OOP (but these functions will be easy to transform to methods)
Magick numbers (0, 1, 2, 3 etc)
No array splitting is necessary. Simply create the variables that will store the totals for each of the permutation you want to measure and iterate through your array. Add to appropriate variables based upon the value you observe in ad_type, click_status, and link_status.

Categories