【问题标题】:Extract column from csv data in PHP从PHP中的csv数据中提取列
【发布时间】:2014-12-11 03:20:36
【问题描述】:

我在PHP 中有csv 数据,如下所示(注意,它是包含换行符的文本,而不是文件):

$data = 'A,B,C,D,E,F,G,H
    1,1,2014-12-10,5,1,2,0,2
    2,7,2014-12-09,9,0,,7,2';

如何将列提取为排除标题的数组?例如,如果我想提取第 4 列,它将包括 5 和 9。

更新:我试过了

$te = array_column($data,'D');

我得到错误:Warning: array_column() expects parameter 1 to be array,

【问题讨论】:

  • 使用fgetcsv() 将数据读入一个数组,然后循环遍历数组以提取您想要的列。对于 PHP 5.5+,您可以使用 array_column() Reference
  • 没有尝试?试试fgetcsv()
  • 不确定您是否只是 PHP 新手,但您的第一站是大多数“我如何...?”问题应该是PHP手册。如果很多人不得不在某个时候这样做,那么它可能内置了三种不同的功能。
  • 好吧,如果这是重复的,也许你可以链接,否则似乎是一个合理的问题,非常感谢一个完整的答案!
  • 这是一个 XY 问题。您正在询问是否提取列,但远不清楚数据的格式,或者您打算如何首先处理它。您的更新显示了一个未知对象的方法,该方法以未指定的格式返回数据。提供适当的上下文,你会得到一个很好的答案。问一个模糊的问题,你会得到猜测。

标签: php arrays csv


【解决方案1】:

您可以使用str_getcsv() 将每一行作为数组读取(丢弃第一个跳过标题)。然后只保留相关列,例如:

$lines = preg_split("/(?:\r?\n|\r\n?)/", $data); // Split lines
array_shift($lines);                             // Discard header

$result = array();
foreach ($lines as $csv) {
    $row = str_getcsv($csv);
    $result[] = $row[3];
}
var_dump($result);

根据下面评论中的 cHao 建议,如果您需要更强大的通用 CSV 数据支持,您可以将字符串转储到虚拟文件并改用 fgetcsv()(它已经正确处理多行输入的解析):

$fp = fopen('php://temp', 'r+');
fputs($fp, $data);
fseek($fp, 0);

$result = array();
fgetcsv($fp);
while (false != ($row = fgetcsv($fp))) {
    $result[] = $row[3];
}
fclose($fp);
var_dump($result);

【讨论】:

  • 注意:CSV 是字符串,而不是文件。你介意修改吗?
  • 您可以使用str_getcsv 将一行转换为一个数组。或者,直接写到php://temp,倒回文件指针,仍然可以使用fgetcsv
  • 注意,如果数据本身可以有换行符,那么天真的“由换行符分割”将会中断。不过,也不确定fgetcsv 处理得如何。
  • @cHao 你有更好的主意吗?
  • @cHao 好点,虽然样本输入并没有给我那种感觉。如果是这种情况,那就是调整正则表达式的问题,因为 CSV 数据应该有某种方式来区分行尾和嵌入的换行符
【解决方案2】:

如果这是一个逗号分隔的字符串,您可以在这种情况下使用str_getcsv()

// load the string and explode, then apply str_getcsv
$data = array_map('str_getcsv', explode("\n", $request->getResponseBody()));
array_shift($data); // remove the header
$fourth_column = array();
foreach($data as $line) {
    if(!empty($line[3])) {
        $fourth_column[] = $line[3]; // indices start at zero
    }   
}

【讨论】:

  • 感谢您的回答。但是,我收到通知:未定义的偏移量:3(在 foreach 循环内的行上)
  • @CodeGuy 这假设你的$data 相当于$request->getResponseBody() 这是正确的吗?我刚用了你贴的那个。这是一个演示codepad.viper-7.com/dee32U。不管怎样 var_dump($line); 在 foreach 里面告诉我它的样子
  • 是的,$data 和 $request->getResponseBody() 一样
  • @CodeGuy 那么这应该可以正常工作,看:[3]=> string(1) "5" 第一个 $line,第二个迭代:[3]=> string(1) "9"。查看我已经设置的 cmets 上方的现场演示
  • @Ghost:更多是因为每一行——即使是最后一行——最后都有一个换行符,根据 CSV 的定义......和explode("\n", "a\n") === ['a', '']。你可以trim在拆分之前关闭它,或者在之后弹出最后一个条目,但它在那里是正常的。
猜你喜欢
  • 2019-11-04
  • 2021-06-22
  • 2015-05-24
  • 1970-01-01
  • 2011-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-22
相关资源
最近更新 更多