【问题标题】:str_getcsv into a multidimensional array in phpstr_getcsv 转换为 php 中的多维数组
【发布时间】:2012-01-11 07:09:03
【问题描述】:

我有这样的 csv 值:

$csv_data = "test,this,thing
             hi,there,this
             is,cool,dude
             have,fun";

我想获取一个完整的 CSV 字符串并将其读入一个多维数组,以便得到:

array(
   array(
      'test' => 'hi',
      'this' => 'there',
      'thing' => 'this'
   ),
   array(
      'test' => 'is',
      'this' => 'cool',
      'thing' => 'dude'
   ),
   array(
      'test' => 'have',
      'this' => 'fun',
      'thing' => ''
   )
);

我想要这样的输出,请注意 CSV 值是动态的。

【问题讨论】:

  • CSV数据的最后一行是否应该有一个逗号?如果行的列数不同,则似乎不是有效的 CSV 数据。或者代码是否需要考虑不同数量的列?
  • 类似,第一行是数组的键,然后是它的值。在 'thing' => '' 部分,这是正确的。
  • 我明白了,但 CSV 数据的最后一行是 have,fun,它只有两列,而不是像其他行那样的三列。我们是否需要考虑列数错误的行?
  • 好的,我已经更新了我的答案以反映两种情况(相同或不同的列数)。
  • 这是我见过的最奇怪的“关闭”实例之一。这是关于如何将 CSV 字符串解析为数组的一个非常普遍且有用的问题。我或多或少有同样的问题,这就是我来到这里的原因。

标签: php csv


【解决方案1】:

假设 CSV 数据中的每一行都有相同的列数,这应该可行。

$lines = explode("\n", $csv_data);
$head = str_getcsv(array_shift($lines));

$array = array();
foreach ($lines as $line) {
    $array[] = array_combine($head, str_getcsv($line));
}

如果行的列数可变(如您的示例中,最后一行有 2 列而不是 3 列),请改用此循环:

foreach ($lines as $line) {
    $row = array_pad(str_getcsv($line), count($head), '');
    $array[] = array_combine($head, $row);
}

【讨论】:

  • 那么在单个字段中包含 \n 的 csv 数据呢? csv 中的常用符号是用引号将这些字段括起来,例如“某个字段中的某个值”。因此,在解析时必须忽略那些 \n 。你的爆炸方法会切断它们。
  • @ChrisPillen 虽然不是提问者的要求之一,但这是一个有效的观点。你认为最好的补救措施是什么?将 CSV 数据保存到 tmpfile() 并使用 fgetcsv() 将其解析回来?我应该在我的答案中添加一个例子吗?
  • @Wiseguy 您可以使用正则表达式来解析数据,但使用临时文件和fgetcsv() 会更简单、更简洁。
【解决方案2】:

这是一个完整的解决方案:

$lines = explode("\n", $csv_data);
$formatting = explode(",", $lines[0]);
unset($lines[0]);
$results = array();
foreach ( $lines as $line ) {
   $parsedLine = str_getcsv( $line, ',' );
   $result = array();
   foreach ( $formatting as $index => $caption ) {
      if(isset($parsedLine[$index])) {
         $result[$formatting[$index]] = trim($parsedLine[$index]);
      } else {
         $result[$formatting[$index]] = '';
      }
   }
   $results[] = $result;
}

那么我们在这里做什么?

  • 首先,您的 CSV 数据被分成带有explode 的行数组
  • 由于 CSV 中的第一行描述数据格式,它必须与实际数据行(explodeunset)分开
  • 为了存储结果,我们初始化了一个新数组 ($results)
  • Foreach 用于逐行遍历数据。对于每一行:
    • 使用 PHP 的 str_getcsv 解析行
    • 一个空的结果数组被初始化
    • 根据格式检查每一行。添加单元格并用空字符串填充缺失的列。

【讨论】:

  • 我想要的输出不正确,谢谢你的回答:)
  • 我认为这是一个更复杂的问题。检查修改后的答案。后面会有详细的解释。
  • 已添加说明。鉴于您的描述,这应该可以回答问题。
【解决方案3】:

这是一个非常干净和简单的解决方案:

function parse_row($row) {
  return array_map('trim', explode(',', $row));
}

$rows   = str_getcsv($csv_data, "\n");
$keys   = parse_row(array_shift($rows));
$result = array();

foreach ($rows as $row) {
  $row = parse_row($row);
  $row = array_pad($row, 3, NULL);

  $result[] = array_combine($keys, $row);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-17
    • 2011-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多