Page 1 of 1
Need help groupping complex array
Posted: Tue Jun 26, 2007 3:09 am
by rustem
Hi,
I am coding the airplane tickets reservation system. When I receive search results from the flights database, many of the flights have the same price, but timing and some other info is different. So, I need to group all the flgiht offers by price. Sounds easy, but there is one problem when we deal with roundtrip flights (they have 2 "sectors" how we call them, one outbound, one inbound). I need to allow user to select one of the flight segments for each sector. However, if there are many available flight segments in one goup (2 or more for each flight sector) it is possible that some combination of the flight segments will not be valid, i.e. there is no flight offer with such flight segments.
Here is schematic code to illustrate this:
Code: Select all
$offers = array( array('flight_id'=>x , 'outbound'=>y, 'inbound'=>z, 'price'=n), ... );
"x", "y", and "z" can be some codes, "n" is price (integer).
So, as you see, each offer has its id, price, and outboud/inboud flight ids. $offers array may contain up to 200 of such offers. (By the way, there is a lot more information in each offer, so code needs to be efficient).
I need to group offers by price. Each group should contain price, outbound ids list and inbound ids list. Flight id can be found later by the combination of outbound and inbound ids (it's unique). A group should not contain any combination of the outbound and inbound ids that is not found in some offer. So, it is possible that there will be several groups with the same price.
I hope you find this interesting and challenging problem to solve. I simply cannot come up with any idea.
Thanks for your help!
Re: Need help groupping complex array
Posted: Tue Jun 26, 2007 3:38 am
by volka
rustem wrote:When I receive search results from the flights database
grouping, ordering, ... isn't your database capable of doing this?
Posted: Tue Jun 26, 2007 4:02 am
by rustem
If it could be done using database, fine. I just don't know how and ask for your help.
Re: Need help groupping complex array
Posted: Tue Jun 26, 2007 4:18 am
by volka
rustem wrote:A group should not contain any combination of the outbound and inbound ids that is not found in some offer.
How can you tell the offers apart?
Re: Need help groupping complex array
Posted: Tue Jun 26, 2007 4:49 am
by rustem
volka wrote:rustem wrote:A group should not contain any combination of the outbound and inbound ids that is not found in some offer.
How can you tell the offers apart?
I don't understand the question.
Posted: Tue Jun 26, 2007 5:13 am
by volka
rustem wrote:A group should not contain any combination of the outbound and inbound ids that is not found in some offer.
Please explain in more detail.
Exactly what is an offer?
What in/outbound ids belong to one offer?
Posted: Tue Jun 26, 2007 6:21 am
by rustem
volka wrote:rustem wrote:A group should not contain any combination of the outbound and inbound ids that is not found in some offer.
Please explain in more detail.
Exactly what is an offer?
What in/outbound ids belong to one offer?
Sorry. I call "offer" a flight offer, returned from the database (actually, it comes from the reservation system called Amadeus). It has, among other information, inbound and outbound ids and price. A s I said each flight (or "offer") has outbound and inbound segments (flights out and back) with their ids. The in/outbond ids can be the same in different offers, however, the
combination of those ids is unique for each offer.
In other words, if I fly out on flight No. 20 ("outbound") and come back on flight No. 50 ("inbound"), the price would be 200 dollars. I can also fly out with No. 20, but come back with No. 60, but the price would be the same. So, we have a group of offers with the price $200, outbound id 20, and inbound ids 50 and 60. (And there won't be any other offers with 20/50 or 20/60 combination priced $200, get it?).
Now, suppose that among other 200 offers we have 2 offers with the same price of $100 and with the following combinations of out/inbound ids: 10/50 and 20/60. If we simply group by price, we get here one group with price $100, outbound ids 10 and 20, and inbound ids 50 and 60. If I show this group to the user so he could choose which flights he'll fly there and back, he might select a combination 10/60 or 20/50. However, there are no such combinations of out/inbound ids with price $100! So, the user will select non-existent offer, and reservation won't be possible. Therefore, in this case I need to make two groups, not one. First would have out/inbound ids 10 and 50 and other will have 20 and 60, both will have price $100.
This is more simple case, ther can be more complicated ones.
Posted: Tue Jun 26, 2007 6:49 am
by volka
Ah, so you already get all possible combinations from that database and they only have to be arranged in a more convinient way.
Is this Amadeus like an sql database? Can you specify a sort order or even two? Something like ORDER BY price,outbound?
Posted: Tue Jun 26, 2007 7:37 am
by rustem
volka wrote:Ah, so you already get all possible combinations from that database and they only have to be arranged in a more convinient way.
Is this Amadeus like an sql database? Can you specify a sort order or even two? Something like ORDER BY price,outbound?
Exactly!
Actually, I get information from Amadeus using SOAP Web Servise. I cannot make sql queries, I get info using supplied SOAP methods.
I can, however, record the received information into our own MySQL DB and do queries from there. I tired this, and it's easier way for simple groupping by price. However, I cannot come up with any idea how to do groupping the correct way, either using DB or not.
Here is the query I came up with for simple groupping by price.
Code: Select all
mysql_query('SELECT `price`, GROUP_CONCAT(DISTINCT `outbound` SEPARATOR ",") as `outbounds`, GROUP_CONCAT(DISTINCT `inbound` SEPARATOR ",") AS `inbounds` FROM `offers_tmp`WHERE `search_id` = "20070626012911" GROUP BY `price`');
Posted: Tue Jun 26, 2007 9:06 am
by volka
I'm not sure wether you need a complex grouping.
Let's assume you get the records orderd by price,out. Then you can do something like
Code: Select all
<?php
$previousPrice = NULL;
$previousOut = NULL;
echo '<table border="1">
<tr><th>out</th><th>in</th></tr>';
while( false!==($row=fake_fetch_array()) ) {
if ( $previousPrice!==$row['price'] ) {
echo '<tr><th colspan="2">price: ', $row['price'], '</th></tr>';
$previousPrice = $row['price'];
$previousOut=NULL;
}
echo '<tr>
<td>', $previousOut!==$row['out'] ? 'out: '.$row['out'] : ' ', '</td>
<td> in:', $row['in'], '</td>
</tr>';
$previousOut = $row['out'];
}
echo '</table>';
function fake_fetch_array() {
static $rows = array(
array(null),
array('price'=>'100.0', 'out'=>'10', 'in'=>'20'),
array('price'=>'100.0', 'out'=>'10', 'in'=>'30'),
array('price'=>'100.0', 'out'=>'40', 'in'=>'20'),
array('price'=>'100.0', 'out'=>'40', 'in'=>'50'),
array('price'=>'100.0', 'out'=>'40', 'in'=>'60'),
array('price'=>'110.0', 'out'=>'10', 'in'=>'25'),
array('price'=>'110.0', 'out'=>'10', 'in'=>'35'),
array('price'=>'110.0', 'out'=>'40', 'in'=>'25'),
array('price'=>'110.0', 'out'=>'40', 'in'=>'55'),
false
);
return next($rows);
}
(quick&dirty example)
Would that suffice?
Posted: Tue Jun 26, 2007 9:29 am
by rustem
Thanks for reply.
Here is what I need to do:
http://avia.lt.sezamas.serveriai.lt/ScreenShot008.gif.
The code you wrote is close to that, but has exactly same problem: the result is wrong, because it would allow user to select combinations like 40/30 or 10/50, which are invalid - there is no element in the array with such 'in' and 'out' combination.
Posted: Tue Jun 26, 2007 9:45 am
by volka
rustem wrote:The code you wrote is close to that, but has exactly same problem: the result is wrong, because it would allow user to select combinations like 40/30 or 10/50, which are invalid
Actually no, the code doesn't allow any choices at all

It only prints all given combinations as a table.
Ok, same
simple, ugly example with radio buttons
Code: Select all
<html>
<head><title>...</title></head>
<body>
<pre><?php print_r($_POST); ?></pre>
<?php
$previousPrice = NULL;
$previousOut = NULL;
echo '<form method="post" action="?"><table border="1">
<tr><th>out</th><th>in</th></tr>';
while( false!==($row=fake_fetch_array()) ) {
if ( $previousPrice!==$row['price'] ) {
echo '<tr><th colspan="3">price: ', $row['price'], '</th></tr>';
$previousPrice = $row['price'];
$previousOut=NULL;
}
echo '<tr>
<td>', $previousOut!==$row['out'] ? 'out: '.$row['out'] : ' ', '</td>
<td> in:', $row['in'], '</td>
<td><input type="radio" name="flight" value="', $row['out'].'_'.$row['in'], '" />
</tr>';
$previousOut = $row['out'];
}
echo '<tr><td colspan="3"><input type="submit" /></td><tr></table>';
function fake_fetch_array() {
static $rows = array(
array(null),
array('price'=>'100.0', 'out'=>'10', 'in'=>'20'),
array('price'=>'100.0', 'out'=>'10', 'in'=>'30'),
array('price'=>'100.0', 'out'=>'40', 'in'=>'20'),
array('price'=>'100.0', 'out'=>'40', 'in'=>'50'),
array('price'=>'100.0', 'out'=>'40', 'in'=>'60'),
array('price'=>'110.0', 'out'=>'10', 'in'=>'25'),
array('price'=>'110.0', 'out'=>'10', 'in'=>'35'),
array('price'=>'110.0', 'out'=>'40', 'in'=>'25'),
array('price'=>'110.0', 'out'=>'40', 'in'=>'55'),
false
);
return next($rows);
}
</body>
</html>
The idea is to group the output by remembering the previous value and starting a "new group" if the value changes.
Sometimes that is sufficent, often it's not.
You might also want to look into xsl(t) to transform the webservices response "directly" to your needs.
see
http://www.w3schools.com/xsl/ and
http://www.google.de/search?&q=xsl
Posted: Wed Jun 27, 2007 1:40 am
by rustem
feyd | Please use Code: Select all
and [syntax="..."] tags where appropriate when posting code. Your post has been edited to reflect how we'd like it posted. Please read: [url=http://forums.devnetwork.net/viewtopic.php?t=21171]Posting Code in the Forums[/url] to learn how to do it too.[/color]
Well, I can see that you don't understand, what I need. First, the user must be able to select both in and out flights. Secondly, in each price group not only 'out' flights must not repeat, but also 'out' flights.
This is how the output should look:
[syntax="html"]<table border="1" width="300">
<tr>
<td colspan="2"><h3>$100</h3></td>
</tr>
<tr><td colspan="2"><strong>Flights out</strong></td></tr>
<tr><td width="270"> Flight 10</td><td width="30" align="center"><input type="radio" name="flight_out" value="10" /></td></tr>
<tr><td width="270"> Flight 40</td><td width="30" align="center"><input type="radio" name="flight_out" value="40" /></td></tr>
<tr><td colspan="2"><strong>Flights in</strong></td></tr>
<tr><td width="270"> Flight 20</td><td width="30" align="center"><input type="radio" name="flight_in" value="20" /></td></tr>
<tr><td width="270"> Flight 50</td><td width="30" align="center"><input type="radio" name="flight_in" value="50" /></td></tr>
<tr><td width="270"> Flight 60</td><td width="30" align="center"><input type="radio" name="flight_in" value="60" /></td></tr>
<tr><td colspan="2" align="right"><input type="submit" /></td></tr>
</table>
<table border="1" width="300">
<tr>
<td colspan="2"><h3>$110</h3></td>
</tr>
<tr><td colspan="2"><strong>Flights out</strong></td></tr>
<tr><td width="270"> Flight 10</td><td width="30" align="center"><input type="radio" name="flight_out" value="10" /></td></tr>
<tr><td width="270"> Flight 40</td><td width="30" align="center"><input type="radio" name="flight_out" value="40" /></td></tr>
<tr><td colspan="2"><strong>Flights in</strong></td></tr>
<tr><td width="270"> Flight 25</td><td width="30" align="center"><input type="radio" name="flight_in" value="25" /></td></tr>
<tr><td width="270"> Flight 35</td><td width="30" align="center"><input type="radio" name="flight_in" value="35" /></td></tr>
<tr><td width="270"> Flight 55</td><td width="30" align="center"><input type="radio" name="flight_in" value="55" /></td></tr>
<tr><td colspan="2" align="right"><input type="submit" /></td></tr>
</table>
Thirdly, when the user selects those flights, selected combination must exist in an array in $rows. In my example above this is not the case, because it is possible to select, for instance, out=10 and in=50, but there is no such roundtrip flight.
You see, I myself can make the grouping to get the above given output. Buе I cannnot eliminate the possiblility to select invalid flight combinations.
feyd | Please use[/syntax]Code: Select all
and [syntax="..."] tags where appropriate when posting code. Your post has been edited to reflect how we'd like it posted. Please read: [url=http://forums.devnetwork.net/viewtopic.php?t=21171]Posting Code in the Forums[/url] to learn how to do it too.[/color]
Posted: Wed Jun 27, 2007 5:21 am
by volka
rustem wrote:Well, I can see that you don't understand, what I need.
Actually I see you haven't understood the example at all.
rustem wrote:First, the user must be able to select both in and out flights.
They can in my example. Take a closer look at the output. And please realize that it's only an example.
rustem wrote:Secondly, in each price group not only 'out' flights must not repeat, but also 'out' flights.
rustem wrote:Thirdly, when the user selects those flights, selected combination must exist in an array in $rows
In my example you cannot select a combination that is not in the array <=> you can only select combinations that are in the array.
It might be better if we stop this discussion (I will for sure) and you take a look at xsl(t).