【问题标题】:Getting specific CSV columns or nth values from a PHP array从 PHP 数组中获取特定的 CSV 列或第 n 个值
【发布时间】:2014-08-14 23:00:07
【问题描述】:

我正在使用 PHP 打开并解析一个非常小的(大约 1kb)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>\r\n");
        foreach ($data as $index=>$val) {
            echo("\t<td>");
            echo htmlentities($val, ENT_QUOTES);
            echo("</td>\r\n");
        }
    echo("</tr>\r\n");
    }
    echo("</table>");
    fclose($handle);
?>

但我一直无法弄清楚如何获取城市、国家/地区数据并删除重复项。有人有建议吗?

【问题讨论】:

  • 我希望$index == 2 拥有城市,$index == 3 拥有国家。要删除重复项,您需要参考数据数组或将信息存储在对用户更友好的数组中,以跟踪写入的内容。

标签: php arrays csv


【解决方案1】:

试试这个:(暂时无法访问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 的每一行填充这些数组。之后,城市和国家列被清除重复值。如上所述,这段代码应该可以工作,但我无法对其进行测试,如果它没有给我留下评论,我一定会在今天下午晚些时候修复它。

【讨论】:

    【解决方案2】:

    $data[2] 包含城市,在将所有城市值推送到数组后应用 array_unique(...) 将删除重复项。

    $cities = array();
    
    while (($data = fgetcsv($handle, 1000, ",")) !== false) {
        $cities[] = $data[2];
    }
    
    $cities = array_unique($cities);
    
    print_r($cities);
    

    参考php manual,里面还有一堆示例代码。

    【讨论】:

      【解决方案3】:

      在处理具有标题行的 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>';
      ?>
      

      【讨论】:

      • 感谢您提供的出色示例。我注意到,当我尝试实现这个和print_r($locations) 时,我得到一个空数组:Array( [0] =&gt; , )
      • @Marcectura:抱歉,标头值中缺少trim。我已经更新了答案。
      【解决方案4】:

      这是一种简单的方法,可以删除重复的城市,而无需实际过滤它们。

      $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>';
      

      【讨论】:

        【解决方案5】:

        在 CSV 句柄循环中,首先,城市和国家字段用逗号连接,并检查 $city_countries 数组。如果没有欺骗,城市国家字符串被写入 $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>\r\n");
            foreach ($data as $index=>$val) {
                echo("\t<td>");
                echo htmlentities($val, ENT_QUOTES);
                echo("</td>\r\n");
            }
            echo("</tr>\r\n");
        }
        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
        )
        

        【讨论】:

        • 感谢您的示例 - 不过,看起来重复的值正在打印。
        • 啊,我明白了 - 代码正在解析整行以查找重复项。我想仅删除 City, Country 列中的重复项,因此 city,country 数组中应该只有一个“马德里,西班牙”,而不应过滤全名/位置/语言表中的重复项跨度>
        • 啊。调整代码以列出所有记录,并存储唯一的城市、国家/地区组合。
        【解决方案6】:

        我看了上面的帖子。

        它不能正常工作 - 所以这里更新了 James Hunt 的工作代码。

        <?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]
        
        ?>
        

        敬请期待 - 问候罗伯特!

        【讨论】:

          猜你喜欢
          • 2023-03-20
          • 1970-01-01
          • 1970-01-01
          • 2022-10-14
          • 1970-01-01
          • 2013-02-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多