views:

92

answers:

3

Hello,

I have weather forecast data formatted like so:

loc_id#location#state#forecast_date#issue_date#issue_time#min_0#max_0#min_1#max_1#min_2#max_2#min_3#max_3#min_4#max_4#min_5#max_5#min_6#max_6#min_7#max_7#forecast_0#forecast_1#forecast_2#forecast_3#forecast_4#forecast_5#forecast_6#forecast_7#
090180#Airey's Inlet#VIC#20091204#20091204#161830###12#19#12#21#12#19#12#17#11#20#12#20#11#17#Mostly clear.#Shower or two.#Light shower or two.#Shower or two.#Rain. Windy.#Shower or two. Windy.#Showers. Windy.#Few showers.#
072146#Albury / Wodonga#VIC#20091204#20091204#162014###11#25#11#29#14#32#17#25#9#27#12#28#12#23#Clear.#Sunny.#Sunny.#Mostly sunny.#Few showers. Windy.#Morning cloud.#Partly cloudy.#Morning cloud.#
089085#Ararat#VIC#20091204#20091204#161830###8#21#7#24#9#24#10#19#8#22#8#22#8#19#Mostly clear.#Afternoon shower or two.#Mostly sunny.#Shower or two.#Shower or two.#Shower or two. Windy.#Shower or two.#Shower or two.#
087113#Avalon#VIC#20091204#20091204#161830###11#21#10#24#11#23#12#19#10#23#11#23#11#19#Mostly clear.#Shower or two.#Sunny.#Shower or two developing.#Rain. Windy.#Becoming windy.#Showers. Windy.#Few showers.#
085279#Bairnsdale#VIC#20091204#20091204#161830###10#22#10#25#12#25#13#21#9#26#11#25#11#21#Mostly clear.#Possible afternoon shower.#Mostly sunny.#Possible late shower.#Rain then shower or two.#Partly cloudy.#Shower or two. Windy.#Shower or two.#

And I'm trying to get my head around how I would go about selecting one area (say, Ararat) and put the data available there into an array in an order that makes sense with PHP5. I have limited experience using regular expression and I'm afraid I need some help with this one.

Also, is the formatting of this data standardised or just something proprietary?

Thanks in advance!

+2  A: 

You can use fgetcsv() (or str_getcsv() if you don't have a file handle).

$fp = fopen('test.txt', 'rb') or die('!fopen');

$result = array();
while(!feof($fp)) {
  $result[] = fgetcsv($fp, 0, '#');
}
var_dump($result);

edit: If needed/wanted you can easily make it an associative array.

$fp = fopen('test.txt', 'rb') or die('!fopen');
$keys = fgetcsv($fp, 0, '#');
$result = array();
while(!feof($fp)) {
  if ( false!=($row=fgetcsv($fp, 0, '#')) ) {
    $result[] = array_combine($keys, $row);
  }
}
var_dump($result);

(you might want to "stretch" that code a little for more error handling)

Or add/replace the keys at a later time. E.g. (using a closure, php 5.3+ only)

$fp = fopen('test.txt', 'rb') or die('!fopen');
$result = array();
while(!feof($fp)) {
  $result[] = fgetcsv($fp, 0, '#');
}
// if there is a line break after the last record
// you might want to remove the empty entry
array_filter($result);

// get the field names and combine them with each record
$keys = array_shift($result);
$result = array_map( function($e) use($keys) { return array_combine($keys, $e); } , $result);

var_dump($result);
VolkerK
This method is amazingly simple and efficient but makes it hard to find what you're looking, especially given that the OP wanted to select a specific area easily. The header row will also be in `$result`, which may complicate things more.
Tatu Ulmanen
array_combine to the rescue ;)
VolkerK
+1  A: 

You don't need to use regular expressions. fgetcsv() might handle it OK, but you can easily write your own parse function which will give you an associative array instead of numerically indexed array:

function parse_data($data) {
    $rows = explode("\n", $data);

    $header = array_shift($rows);
    $header_cells = explode("#", $header);

    $result = array();

    foreach($rows as $row) {
        $tmp = array();
        $cells = explode("#", $row);
        // Now $cells[0] has loc_id, $cells[1] has location etc..
        foreach($cells as $id => $cell) {
            $tmp[$header_cells[$id]] = $cell;
        }
        $result[$cells[1]] = $tmp;
    }
    return $result;
}

And use it like this:

$data = parse_data(file_get_contents('data.txt'));

You can use print_r() to output the array to the screen and check it out. The rows are indexed by location, so you can use $data['Ararat']; to get the data for Ararat, and to get specific fields, use for example $data['Ararat']['state'];

Tatu Ulmanen
+1  A: 

This builds an array which has the location name as primary index, it contains other arrays with the fields named as in the first line of the file and relative values.

$str = 'your input as posted in your question';

$lines   = explode("\n", $str);
$headers = explode('#', $lines[0]);
$output  = array();

for ($x = 1; $x < count($lines); $x++) {
    $fields = explode('#', $lines[$x]);
    for ($y = 0; $y < count($fields); $y++) {
        $key         = $fields[1];
        $column_name = $headers[$y];

        $output[$key][$column_name] = $fields[$y];
    }
}

// output
print_r($output);

// example of usage
echo $output['Ararat']['min_3'];
kemp