首页 > 解决方案 > PHP无序关联数组到CSV行匹配标题到键,根据需要创建新标题

问题描述

我有一系列数组,类似:

$my_array = {"foo"=>"bar", "sudo"=>"make_sandwhich", "bam"=>"bang"};

和一个类似的csv:

     Header 1, Header 2, foo, Header 4  , bam      , Header 5
     Lorem.  , Ipsum.  ,    , cheesecake, Henrietta, Loreal
             ,         ,    ,           ,          , New Hampshire

当我从头开始添加示例行时,我希望 csv 看起来像这样......

     Header 1, Header 2, foo, Header 4  , bam      , Header 5     , sudo
     Lorem.  , Ipsum.  ,    , cheesecake, Henrietta, Loreal       ,
             ,         ,    ,           ,          , New Hampshire,
             ,         , bar,           , bang     ,              , make_sandwhich

我试过弄乱 fputcsv,但它似乎没有任何接近我需要的功能。有没有办法做到这一点?

标签: phpcsvassociative-array

解决方案


它可以通过 fgetcsv 和 fputcsv 以及“一些”附加处理来实现。

阅读您的 csv 文件(第一行是标题),然后从您的输入行添加新标题。然后读取行,为新标题创建缺失数据,并在末尾添加一个包含所有标题的新行。然后只需将该数据写回 csv 文件。

a.csv - 输入:

     Header 1, Header 2, foo, Header 4  , bam      , Header 5
     Lorem.  , Ipsum.  ,    , cheesecake, Henrietta, Loreal
             ,         ,    ,           ,          , New Hampshire

代码:

<?php

$myArray = ["foo"=>"bar", "sudo"=>"make_sandwhich", "bam"=>"bang"];

$readHandle = fopen("a.csv", "r");

// get headers (first row)
$headers = fgetcsv($readHandle);

$allHeaders = [];
foreach ($headers as $header) {
  $allHeaders[] = trim($header);
}

// add missing headers from the input data (so to headers from file add sudo header)
foreach (array_keys($myArray) as $data) {
  if (!in_array($data, $allHeaders)) {
    $allHeaders[] = $data;
  }
}
var_dump($allHeaders);

// read all rows from the file and add the new headers
$rows = [];
while($row = fgetcsv($readHandle)) {
  foreach ($allHeaders as $k => $header) {
    $row[$k] = isset($row[$k]) ? trim($row[$k]) : '';
  }

  $rows[] = $row;
}

// add the new row from input data
$newRow = [];
foreach ($allHeaders as $header) {
  $newRow[] = $myArray[$header] ?? '';
}
$rows[] = $newRow;
var_dump($rows);

fclose($readHandle);

// now write headers and rows to csv file
$writeHandle = fopen('b.csv', 'w+');

fputcsv($writeHandle, $allHeaders);

foreach ($rows as $row) {
  fputcsv($writeHandle, $row);
}

fclose($writeHandle);

$所有标题:

array(7) {
  [0]=>
  string(8) "Header 1"
  [1]=>
  string(8) "Header 2"
  [2]=>
  string(3) "foo"
  [3]=>
  string(8) "Header 4"
  [4]=>
  string(3) "bam"
  [5]=>
  string(8) "Header 5"
  [6]=>
  string(4) "sudo"
}

$行:

array(3) {
  [0]=>
  array(7) {
    [0]=>
    string(6) "Lorem."
    [1]=>
    string(6) "Ipsum."
    [2]=>
    string(0) ""
    [3]=>
    string(10) "cheesecake"
    [4]=>
    string(9) "Henrietta"
    [5]=>
    string(6) "Loreal"
    [6]=>
    string(0) ""
  }
  [1]=>
  array(7) {
    [0]=>
    string(0) ""
    [1]=>
    string(0) ""
    [2]=>
    string(0) ""
    [3]=>
    string(0) ""
    [4]=>
    string(0) ""
    [5]=>
    string(13) "New Hampshire"
    [6]=>
    string(0) ""
  }
  [2]=>
  array(7) {
    [0]=>
    string(0) ""
    [1]=>
    string(0) ""
    [2]=>
    string(3) "bar"
    [3]=>
    string(0) ""
    [4]=>
    string(4) "bang"
    [5]=>
    string(0) ""
    [6]=>
    string(14) "make_sandwhich"
  }
}

b.csv - 输出:

"Header 1","Header 2",foo,"Header 4",bam,"Header 5",sudo
Lorem.,Ipsum.,,cheesecake,Henrietta,Loreal,
,,,,,"New Hampshire",
,,bar,,bang,,make_sandwhich

我希望您不希望 csv 中的空格用于格式化。也可以这样做,但您需要保留每列中最长字符串的字符数,并将值填充到该长度。


推荐阅读