php - Group data in csv rows by one column and create comma-separated values from other columns within each group
I've got an old script from someone that I want to remodel but unfortunately I am not that experienced in PHP. What it does is, it reads article information from a CSV file into an array and then basically posts the output into a HTML table, which can then be saved into a PDF file.
One thing I couldn't quite wrap my head around is, the file provides duplicate lines for an article while only some values changed (size, color etc). The article does have the same name but is not repeated twice in the output, the "new" values are just added to the already existing record and I am quite unsure how to do that. Let me give you a simplified example:
CSV Example:
ArtNo,Name,Color,Size
DEF270, Fingal, Stellar, 3XL
DEF270, Fingal, White, 4XL;
So, in a regular loop, the output would be like this
ArtNo | Name | Color | Size |
---|---|---|---|
DEF270 | Fingal | Stellar | 3XL |
DEF270 | Fingal | White | 4XL |
Answer
Solution:
Let you loaded data from CSV to plain array. After this you can apply array_reduce
in next way:
$res = array_reduce(
$rows,
function($res, $row) {
if (isset($res[$row[0]])) {
$res[$row[0]][1] .= ", $row[1]";
$res[$row[0]][2] .= ", $row[2]";
$res[$row[0]][3] .= ", $row[3]";
}
else $res[$row[0]] = $row;
return $res;
},
[]
);
var_export($res);
Answer
Solution:
You can process the whole file by grouping the article number and add the properties to each an array. On output you implode them comma delimited.
$csv = <<<'_CSV'
ArtNo,Name,Color,Size
DEF270, Fingal, Stellar, 3XL
DEF270, Fingal, White, 4XL;
_CSV;
$csv_handle = fopen('php://memory', 'rw');
$fwrite = fwrite($csv_handle, $csv);
fseek($csv_handle, 0);
$articles = [];
while (($data = fgetcsv($csv_handle)) !== false) {
[$articleNumber, $name, $color, $size] = array_map('trim', $data);
if (!isset($articles[$articleNumber])) {
$articles[$articleNumber] = [
'names' => [$name],
'colors' => [$color],
'sizes' => [$size],
];
continue;
}
$article = &$articles[$articleNumber];
if (!in_array($name, $article['names'])) {
$article['names'][] = $name;
}
if (!in_array($color, $article['colors'])) {
$article['colors'][] = $color;
}
if (!in_array($size, $article['sizes'])) {
$article['sizes'][] = $size;
}
unset ($article);
}
fclose($csv_handle);
echo "<table>\n";
foreach ($articles as $articleNumber => $article) {
$names = implode(', ', $article['names']);
$colors = implode(', ', $article['colors']);
$sizes = implode(', ', $article['sizes']);
echo "<tr><td>$articleNumber</td><td>$names</td><td>$colors</td><td>$sizes</tr>\n";
}
echo "</table>\n";
Output
<table>
<tr><td>ArtNo</td><td>Name</td><td>Color</td><td>Size</tr>
<tr><td>DEF270</td><td>Fingal</td><td>Stellar, White</td><td>3XL, 4XL;</tr>
</table>
Source