在管道分隔的flatfile中计算唯一名称和最后一次出现(来自数据)的最明智的方法是什么,其中数据形成如下:
Artist|YYYY-MM-DD|Location|\n
所以当数据是例如(最后用换行符)时:
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|
所需的格式为:
Artist|Times listed|Latest year
如何循环遍历flatfile以将以下数据转换为第二个flatfile:
Le Artist|1|1999|
Soundmakers|3|2012|
The Band|2|2011|
起初我认为这将是一项相当简单的工作,但事实证明它更具挑战性!
我有一个实现半工作(有些项目写了两次,有时候年份是错误的!),所以我想看看是否有更好的方法来实现这一点。
我已经为此尝试了OOP和程序方法,到目前为止,我已经通过程序获得了更好的结果。但对我来说,这个方法并不重要,因为这是我个人的学习(和使用)。
更新: 该文件大约为1 MB,在任何可预见的未来都将远远低于10 MB。
答案 0 :(得分:1)
首先,创建一个以艺术家名称为键的数组,以及作为值的年份列表:
$grouped = array();
while (!feof($fd) && $line = fgets($fd)) {
list($artist, $date) = explode('|', $line);
list($year) = explode('-', $date);
$grouped[$artist][] = $year;
}
然后输出结果:
foreach ($grouped as $artist => $years) {
printf("%s|%s|%s|\n", $artist, count($years), max($years));
}
答案 1 :(得分:1)
看起来确实非常简单。您希望将结果存储为如下数组:
$bands = array(
'Le Artist' => array('count' => 1, 'year' => 1999),
...
);
您可以使用fgetcsv
读取行并同时将它们分开:
$line = fgetcsv($fh, 0, '|');
然后,您可以检查是否已有此艺术家并增加计数:
$artist = $line[0];
if (!isset($bands[$artist])) {
$bands[$artist] = array('count' => 0, 'year' => null);
}
$bands[$artist]['count']++;
对于这一年,只需展开$line[1]
来提取年份,检查它是否大于$bands[$artist]['year']
,如果是,则替换它。
答案 2 :(得分:0)
以下是我最终使用的版本,它的工作原理如我所希望的那样:
<?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/>';
}
?>