Solved

Merge child arrays

Posted on 2012-12-28
5
214 Views
Last Modified: 2012-12-28
I'm trying to find an elegant way of achieving the following:

- merge the "availability_" elements where the "flight_number" matches
- So that there is only one child array for each flight number (i.e. delete any further child arrays after the merge)
- Note: There won't be an occurrence where there are conflicting "availability_" values for the same flight number
- If no availability_ value is set for a given flight number, set it to 0.

I would like to turn this:

Array
(
    [0] => Array
        (
            [flight_number] => BA0179
            [availability_first] => 
            [availability_business] => 
            [availability_economy] => 99
            [flight_departure] => 2013-10-16 12:40
        )
    [1] => Array
        (
            [flight_number] => BA0213
            [availability_first] => 
            [availability_business] => 
            [availability_economy] => 6
            [flight_departure] => 2013-10-16 13:40
        )
    [2] => Array
        (
            [flight_number] => BA0179
            [availability_first] => 
            [availability_business] => 1
            [availability_economy] => 
            [flight_departure] => 2013-10-16 12:40
        )
)

Open in new window


into

Array
(
    [0] => Array
        (
            [flight_number] => BA0179
            [availability_first] => 0
            [availability_business] => 1
            [availability_economy] => 99
            [flight_departure] => 2013-10-16 12:40
        )
    [1] => Array
        (
            [flight_number] => BA0213
            [availability_first] => 0
            [availability_business] => 0
            [availability_economy] => 6
            [flight_departure] => 2013-10-16 13:40
        )
)

Open in new window

0
Comment
Question by:benwiggy
  • 3
5 Comments
 
LVL 109

Expert Comment

by:Ray Paseur
ID: 38727356
I could see using usort() to sort by flight number, then using an iterator like foreach to walk the resulting array.  I'll try to show you a code example in a few minutes.
0
 
LVL 109

Assisted Solution

by:Ray Paseur
Ray Paseur earned 250 total points
ID: 38727433
This looks OK to me.  See http://www.laprbass.com/RAY_temp_benwiggy.php

<?php // RAY_temp_benwiggy.php
error_reporting(E_ALL);
echo '<pre>';

// TEST DATA
$td = Array
(
    '0' => Array
        (   'flight_number' => 'BA0179'
        ,   'availability_first' => ''
        ,   'availability_business' => ''
        ,   'availability_economy' => 99
        ,   'flight_departure' => '2013-10-16 12:40'
        )
,   '1' => Array
        (   'flight_number' => 'BA0213'
        ,   'availability_first' => ''
        ,   'availability_business' => ''
        ,   'availability_economy' => 6
        ,   'flight_departure' => '2013-10-16 13:40'
        )
,   '2' => Array
        (   'flight_number' => 'BA0179'
        ,   'availability_first' => ''
        ,   'availability_business' => 1
        ,   'availability_economy' => ''
        ,   'flight_departure' => '2013-10-16 12:40'
        )
)
;
// DOES IT LOOK RIGHT? (YES)
print_r($td);

// SORT BY FLIGHT NUMBER
function flight_sort($a, $b)
{
    if ($a["flight_number"] == $b["flight_number"]) return 0;
    return ($a["flight_number"] < $b["flight_number"]) ? -1 : 1;
}
usort($td, 'flight_sort');

// CREATE A TEMPLATE WITH ZERO VALUES
$tmp = $td[0];
foreach ($tmp as $key => $val) $tmp[$key] = 0;

// SET UP FOR THE ITERATOR
$sum = $tmp;
$out = array();
$old_flight_number = FALSE;

// ITERATE OVER THE TEST DATA
foreach ($td as $now)
{
    // IF A NEW FLIGHT NUMBER
    if ($now['flight_number'] != $old_flight_number)
    {
        // SAVE THE LAST SUMMARY
        $out[] = $sum;

        // SET A NEW FLIGHT NUMBER
        $old_flight_number = $now['flight_number'];

        // COPY THE TEMPLATE
        $sum = $tmp;
    }

    // WHETHER OR NOT A NEW FLIGHT NUMBER, FILL IN THE PARTS
    foreach ($now as $key => $val)
    {
        if (substr($key,0,1) == 'f') $sum[$key] = $val;
        if (substr($key,0,1) == 'a') $sum[$key] += $val;
    }
}

// APPEND LAST FLIGHT
$out[] = $sum;

// DECLOP THE TEMPLATE
unset($out[0]);

// SHOW THE WORK PRODUCT
print_r($out);

Open in new window

Best regards, ~Ray
0
 
LVL 82

Accepted Solution

by:
hielo earned 250 total points
ID: 38727585
My suggestion would be to convert the data into:
$flights=Array
(
    [BA0179] => Array
        (
            [availability_first] => 0
            [availability_business] => 1
            [availability_economy] => 99
            [flight_departure] => 2013-10-16 12:40
        )
    [BA0213] => Array
        (
            [availability_first] => 0
            [availability_business] => 0
            [availability_economy] => 6
            [flight_departure] => 2013-10-16 13:40
        )
)

Open in new window


The advantages of the new structure are:
a. fewer elements - the [flight_number] key no longer exists.  Intead, the actual flight number becomes the top-level key.
b. easier to find/search details for a flight number - ex:
$id='BA0213';
if( isset($flights[$id]) )
{
   //if it makes it here, the flight exists
   print_r($flights[$id]);
}

Try the code below:
$data=Array(
    '0' => Array(
            'flight_number' => 'BA0179'
            ,'availability_first' => NULL
            ,'availability_business' => NULL
            ,'availability_economy' => 99
            ,'flight_departure' => '2013-10-16 12:40'
        )
    ,'1' => Array(
            'flight_number' => 'BA0213'
            ,'availability_first' => NULL
            ,'availability_business' => NULL
            ,'availability_economy' => 6
            ,'flight_departure' => '2013-10-16 13:40'
        )
    ,'2' => Array(
            'flight_number' => 'BA0179'
            ,'availability_first' => NULL
            ,'availability_business' => 1
            ,'availability_economy' => NULL
            ,'flight_departure' => '2013-10-16 12:40'
        )
);

$flights=Array();
foreach($data as $f)
{
	$id=$f['flight_number'];

        //this gets rid of the flight_number key/element
	unset($f['flight_number']);

	$f['availability_first']=(int)$f['availability_first'];
	$f['availability_business']=(int)$f['availability_business'];
	$f['availability_economy']=(int)$f['availability_economy'];

	if(!isset($flights[$id]))
	{
		$flights[$id]=Array();
	}
	else
	{
		$f['availability_first']=max($f['availability_first'],$flights[$id]['availability_first']);
		$f['availability_business']=max($f['availability_business'],$flights[$id]['availability_business']);
		$f['availability_economy']=max($f['availability_economy'],$flights[$id]['availability_economy']);
	}
	$flights[$id]=array_merge($flights[$id], $f);
	
}
unset($data);
echo '<pre>';
print_r($flights);

Open in new window

0
 
LVL 6

Author Comment

by:benwiggy
ID: 38727670
Thanks for the suggested solutions and feedback. I've realised that the easiest thing to do is use the flight number as the key (as suggested) - this enables me to include the availability counts as I build out the array.

As the suggested solutions helped me solve the problem, will award points.
0
 
LVL 109

Expert Comment

by:Ray Paseur
ID: 38727790
Thanks for the points and thanks for using EE.  Going forward you might want to think about using object-oriented notation.  It is often more flexible than array notation.  You might also want to think about what happens if you have the same flight number on different days, or with different "legs" and the same flight number.  These factors may influence the data structure.

Best regards, ~Ray
0

Featured Post

Does Powershell have you tied up in knots?

Managing Active Directory does not always have to be complicated.  If you are spending more time trying instead of doing, then it's time to look at something else. For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Deprecated and Headed for the Dustbin By now, you have probably heard that some PHP features, while convenient, can also cause PHP security problems.  This article discusses one of those, called register_globals.  It is a thing you do not want.  …
Part of the Global Positioning System A geocode (https://developers.google.com/maps/documentation/geocoding/) is the major subset of a GPS coordinate (http://en.wikipedia.org/wiki/Global_Positioning_System), the other parts being the altitude and t…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.

778 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question