#php #arrays #csv
#php #массивы #csv
Вопрос:
Я использую PHP для открытия и анализа очень маленького (около 1 КБ) CSV-файла для создания HTML-таблицы. Я новичок в PHP, и это в значительной степени экспериментально. В дополнение к созданию таблицы HTML я пытаюсь сгенерировать массив из определенного набора столбцов в этом csv (информация о городе и стране), а затем удалить повторяющиеся значения.CSV структурирован следующим образом:
Last Name, First Name, City, Country, Language
Smith, Joe, Shanghai, China, English
Jackson, Stacey, Madrid, Spain, Spanish
Jones, Bob, London, United Kingdom, English
Seward, Elisa, Madrid, Spain, English
Harrison, Tim, Berlin, Germany, German
Идея здесь в том, что в дополнение к таблице со всеми данными у меня также будет список всех городов / стран, перечисленных в таблице:
- Шанхай, Китай
- Мадрид, Испания
- Лондон, Великобритания
- Берлин, Германия
Благодаря fgetcsv()
документации и другим вопросам по Stack Overflow, чтение файла и построение таблицы просты:
<?php
$handle = fopen("namelist.csv", "r");
$data = fgetcsv($handle, 1000, ",");
echo('<table>');
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
echo("<tr>rn");
foreach ($data as $index=>$val) {
echo("t<td>");
echo htmlentities($val, ENT_QUOTES);
echo("</td>rn");
}
echo("</tr>rn");
}
echo("</table>");
fclose($handle);
?>
Но я не смог понять, как получить данные о городе, стране и удалить дубликаты. У кого-нибудь есть предложения?
Комментарии:
1. Я ожидаю, когда
$index == 2
у вас есть город, и когда$index == 3
у вас есть страна. Чтобы удалить дубликаты, вам нужно обратиться к массиву данных или сохранить информацию в более удобном для пользователя массиве, чтобы отслеживать, что было написано.
Ответ №1:
Вот простой способ, который удаляет повторяющиеся города без необходимости их фильтрации.
$fHandle = fopen("namelist.csv", "r");
$aData = fgetcsv($handle, 1000, ",");
while (($aData = fgetcsv($fHandle, 1000, ",")) !== FALSE) {
$aLocations[$aData[3]] = $aData[4];
}
echo '<table>';
foreach ($aLocations as $sCity => $sCountry) {
echo '<tr><td>'.$sCity.'</td><td>'.$sCountry.'</td></tr>';
}
echo '</table>';
Ответ №2:
В цикле обработки CSV сначала поля city и country соединяются запятой и проверяется массив $city_countries. Если нет дубликатов, строка city country записывается в массив $city_countries . Теги TR повторяются, а массив $data зацикливается для записи тегов TD и значений столбцов.
$handle = fopen("namelist.csv", "r");
$data = fgetcsv($handle, 1000, ",");
$city_countries = array();
echo('<table>');
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
$city_country = $data[2] . ', ' . $data[3];
if ( !in_array($city_country, $city_countries) ) {
array_push($city_countries, $city_country);
}
echo("<tr>rn");
foreach ($data as $index=>$val) {
echo("t<td>");
echo htmlentities($val, ENT_QUOTES);
echo("</td>rn");
}
echo("</tr>rn");
}
echo("</table>");
fclose($handle);
print '<pre>'; print_r($city_countries); print '</pre>';
Это входной файл, который я использую:
Last Name, First Name, City, Country, Language
Smith, Joe, Shanghai, China, English
Jackson, Stacey, Madrid, Spain, Spanish
Jackson, Steve, Madrid, Spain, Spanish
Jones, Bob, London, United Kingdom, English
Seward, Elisa, Madrid, Spain, English
Harrison, Tim, Berlin, Germany, German
Jones, Bill, London, United Kingdom, English
Jackson, Ralph, Madrid, Spain, Spanish
И это результат, который я получаю:
Smith Joe Shanghai China English
Jackson Stacey Madrid Spain Spanish
Jackson Steve Madrid Spain Spanish
Jones Bob London United Kingdom English
Seward Elisa Madrid Spain English
Harrison Tim Berlin Germany German
Jones Bill London United Kingdom English
Jackson Ralph Madrid Spain Spanish
Array
(
[0] => Shanghai, China
[1] => Madrid, Spain
[2] => London, United Kingdom
[3] => Berlin, Germany
)
Комментарии:
1. спасибо за пример — похоже, что дублирующиеся значения печатаются.
2. Ах, я вижу — код анализирует всю строку, чтобы найти дубликаты. Я хотел бы удалить дубликаты только в столбце «Город, страна», поэтому в массиве «Город, страна» должно быть только одно «Мадрид, Испания», в то время как таблица полных имен / местоположений / языков не должна фильтроваться на наличие дубликатов
3. Ah. Код изменен, чтобы перечислить все записи и сохранить уникальные комбинации городов и стран.
Ответ №3:
Попробуйте это: (На данный момент у меня нет доступа к PHP, примерно через час будут найдены крошечные ошибки)
<?php
$handle = fopen("namelist.csv", "r");
$data = fgetcsv($handle, 1000, ",");
$csv = array();
$csv[] = array();
$csv[] = array();
$csv[] = array();
$csv[] = array();
$csv[] = array();
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
foreach ($data as $index=>$val) {
$column=0;
$csv[column][] = htmlentities($val, ENT_QUOTES);
$column ;
}
}
fclose($handle);
//Now, csv[0] has all Last Names, csv[1] has all First Names, csv[2] all Cities, csv[3] all Countries and csv[4] all Languages
//To filter duplicates..
$cities = array_unique($csv[2]);
$countries = array_unique($csv[3]);
?>
Это создает массив, содержащий 5 массивов (по одному для каждого столбца). Затем эти массивы заполняются каждой строкой CSV. После этого столбцы city и country очищаются от повторяющихся значений. Как указано выше, этот код ДОЛЖЕН работать, но я не смог его протестировать, если он не оставит мне комментарий, и я обязательно исправлю его позже сегодня днем.
Ответ №4:
$data[2]
содержит город, и применение array_unique(...)
после переноса всех значений города в массив приведет к удалению дубликатов.
$cities = array();
while (($data = fgetcsv($handle, 1000, ",")) !== false) {
$cities[] = $data[2];
}
$cities = array_unique($cities);
print_r($cities);
Обратитесь к руководству по php, в котором также есть несколько примеров кодов.
Ответ №5:
При работе с CSV, которые имеют строку заголовка, я предпочитаю сопоставлять столбцы данных с именованным ключом, поэтому мне не нужно отслеживать, к какому индексу относится конкретный столбец. Это позволяет вам ссылаться $var['ColumnName']
вместо $var[2]
:
<?php
$csvDelim = ',';
$csvEnclosure = '';
$csvArr = file('./namelist.csv', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
//create array of the csv headers
$csvHeaders = str_getcsv(trim(array_shift($csvArr)), $csvDelim, $csvEnclosure);
$csvHeaders = array_map("trim", $csvHeaders);
//get the csv data and make a multi-dim array of keys/values
$dataArr = array();
foreach($csvArr as $csvLine)
{
$lineData = str_getcsv(trim($csvLine), $csvDelim, $csvEnclosure);
$lineData = array_map("trim", $lineData);
$dataArr[] = array_combine($csvHeaders, $lineData);
}
//get unique city/country values
$locations = array();
foreach($dataArr as $da)
$locations[] = $da['City'].', '.$da['Country'];
$locations = array_unique($locations);
//output data in table
echo '<table>';
echo '<tr>';
foreach($csvHeaders as $headerValue)
echo '<th>'.$headerValue.'</th>';
echo '</tr>';
foreach($dataArr as $dataLine)
{
echo '<tr>';
foreach($dataLine as $dataValue)
{
echo '<td>'.htmlentities($dataValue, ENT_QUOTES).'</td>';
}
echo '</tr>';
}
echo '</table>';
?>
Комментарии:
1. спасибо за отличный пример. Я заметил, что когда я пытаюсь реализовать это, и
print_r($locations)
я получаю пустой массив:Array( [0] => , )
2. @Marcatectura: Извините, отсутствовали
trim
значения заголовка. Я обновил ответ.
Ответ №6:
я прочитал сообщение выше.
Это работает некорректно — итак, вот обновленный рабочий код Джеймса Ханта.
<?php
$handle = fopen("test.csv", "r");
$data = fgetcsv($handle, 1000, ";");
$csv = array();
$csv[] = array();
$csv[] = array();
$csv[] = array();
$csv[] = array();
$csv[] = array();
while (($data = fgetcsv($handle, 1000, ";")) !== FALSE) {
$column=0;
foreach ($data as $index=>$val) {
$csv[$column][] = htmlentities($val, ENT_QUOTES);
$column ;
}
}
fclose($handle);
//Now, csv[0] has all Last Names, csv[1] has all First Names, csv[2] all Cities, csv[3] all Countries and csv[4] all Languages
//To filter duplicates..
$cities = array_unique($csv[2]);
$countries = array_unique($csv[3]);
var_dump($cities); //will output all column values of $csv[2]
?>
так что следите за обновлениями — приветствую Роберта!