문제

What is the most sensible way to count unique names and the last occurence (from the data) in a pipe-separated flatfile, where the data is formed like this:

Artist|YYYY-MM-DD|Location|\n

So when the data is for example (with newline in the end):

The Band|2011-04-01|Club Bulc|
Le Artist|1999-12-24|Reindeer Row|
Soundmakers|2012-03-22|Pub Pizza|
The Band|2010-12-01|Someplace|
Soundmakers|2009-07-07|Faraway|
Soundmakers|2010-08-18|ShowEr|

And the desired format would be:

Artist|Times listed|Latest year

How would you loop through the flatfile to get the following data into a second flatfile:

Le Artist|1|1999|
Soundmakers|3|2012|
The Band|2|2011|

At first I thought it would be quite a simple undertaking, but it turned out a bit more challenging!

I have one implementation that half-works (some items are written twice, and sometimes the year is in the wrong line!), so I would like to see if there are some better methods for accomplishing this.

I've tried both an OOP and procedural approach for this, and so far I've gotten better results with procedural. But for me the method really doesn't matter, as this is for my personal learning (and use).

Update: The file is roughly 1 MB and will be far less than 10 MB in any foreseeable future.

도움이 되었습니까?

해결책

Seems pretty simple indeed. You'll want the results to be stored an array like this:

$bands = array(
    'Le Artist' => array('count' => 1, 'year' => 1999),
    ...
);

You can use fgetcsv to read in the lines and break them apart at the same time:

$line = fgetcsv($fh, 0, '|');

You can then check whether you already have this artist and increment the count:

$artist = $line[0];
if (!isset($bands[$artist])) {
    $bands[$artist] = array('count' => 0, 'year' => null);
}
$bands[$artist]['count']++;

For the year, just explode $line[1] to extract the year, check if it's greater than $bands[$artist]['year'] and replace it if so.

다른 팁

First, make an array with artist name as key, and a list of years as values:

$grouped = array();

while (!feof($fd) && $line = fgets($fd)) {
    list($artist, $date) = explode('|', $line);
    list($year) = explode('-', $date);

    $grouped[$artist][] = $year;
}

Then output the result:

foreach ($grouped as $artist => $years) {
    printf("%s|%s|%s|\n", $artist, count($years), max($years));
}

Here is the version I ended up using, and it works as I hoped for:

<?php
$file = 'seen.txt';
$shows = array();
$sourceData = file($file);
foreach($sourceData as $row) {
    list($date, $artist, $venue, $city, $country) = explode('|', $row);
    $year = date('Y', strtotime($date));
    if(!isset($shows[$artist])) {
        $shows[$artist] = array('count' => 1, 'year' => $year);
    } else {
        $shows[$artist]['count']++;
        if($shows[$artist]['year'] < $year) {
            $shows[$artist]['year'] = $year;
        }
    }
}
echo '<h1>Bands and Shows</h1>';
ksort($shows);
foreach($shows as $band => $data) {
    echo 'I have seen <b>',$band,'</b> perform ',$data['count'],' times, most recently in ',$data['year'],'<br/>';
}
?>
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top