【问题标题】:flatten multidimensional array into csv text with PHP使用 PHP 将多维数组展平为 csv 文本
【发布时间】:2011-09-29 19:33:46
【问题描述】:

我知道这个问题已经被问过很多次了,但这有点奇怪。

我有一个多维数组,其中数组的键需要是平面 csv 类型字符串的列名(我不希望它作为文件,只是作为 csv 字符串)。

原来是这样的:

$data = array(
                dates = array ('2010-01-02','2011-02-03','2011-02-04'),
                type1 = array ('data1','data2','data3'),
                type2 = array ('data4','data5','data6')
);

最终结果应该是:

$new_data  = "dates,type1,type2" . "\n"
$new_data .= "2010-01-02,data1,data4" . "\n"
$new_data .= "2011-02-03,data2,data5" . "\n"
$new_data .= "2011-02-04,data3,data6";

我希望这很清楚。感谢您的帮助。

【问题讨论】:

    标签: php csv multidimensional-array


    【解决方案1】:

    这比您可能需要的要详细得多,但它允许您拥有一个包含 n 个元素的数组。 zip 基于同名的 Python 函数。不是我写的。

    $data = ($data);
    $r = (call_user_func_array('zip', $data));
    
    $fin = "";
    $fin .= implode(',',array_keys($data)).PHP_EOL;
    foreach($r as $arr)
    {
        $fin .= implode(',',$arr).PHP_EOL;
    }
    
    // $fin now holds all the data. Do something with it and you're finished!
    
    function zip() {
        $args = func_get_args();
        $zipped = array();
        $n = count($args);
        for ($i=0; $i<$n; ++$i) {
            reset($args[$i]);
        }
        while ($n) {
            $tmp = array();
            for ($i=0; $i<$n; ++$i) {
                if (key($args[$i]) === null) {
                    break 2;
                }
                $tmp[] = current($args[$i]);
                next($args[$i]);
            }
            $zipped[] = $tmp;
        }
        return $zipped;
    }
    

    (查看 cmets 中的对话。这真的很相关。)

    【讨论】:

    • 只是说,这不会根据 RFC 生成有效的 CSV。
    • @hakre 没错,正确的行终止符是\r\n,这意味着上面将在Windows中输出有效的CSV,而不是*nix。
    • 嗯,假设您有一个包含冒号, 或换行符或引号" 或什至是这些的混合的值。与此相比,我认为PHP_EOL 是一个小问题。
    • 考虑过,但这不符合 OP 的预期结果。不过,如果他愿意,他可以将 $fin .= implode(',',$arr).PHP_EOL; 替换为 $fin .= '"' . implode('","',$arr)."\"\r\n";
    • 也就是说,对于实际的 CSV(而不是类似 CSV),使用 PHP_EOL 是不正确的,而不建议使用双引号。
    【解决方案2】:

    这与 Marc B 建议的相同,但是您写道您不想为此创建文件。 Stream Wrappers 的救援(未经测试,只是在我的脑海中浮现):

    $fh = fopen('php://memory', 'rw'); # don't create a file, write to memory instead
    
    // write out the headers
    fputcsv($fh, array_keys($data));
    
    // write out the data    
    for ($i = 0; $i < count($data['dates']); $i++) {
        $temp = array($data['dates'][$i], $data['type1'][$i], $data['type2'][$i]);
        fputcsv($fh, $temp);
    }
    rewind($fh);
    $string = stream_get_contents($fh);
    fclose($fh);
    

    【讨论】:

      【解决方案3】:

      为此我开设了一个小班:https://gist.github.com/981720

      您可以像这样包含它并生成 csv:

      CSV::export($field_names, $data, '', TRUE)

      【讨论】:

      • 此代码没有许可证,因此对我来说无法使用。我只能在它是 MIT 或 BSDL 或非 GPL 的情况下使用它。
      【解决方案4】:

      这样的事情可能会接近你想要的(未经测试,只是想不到):

      $fh = fopen('file.csv', 'w');
      
      // write out the headers
      fputcsv($fh, array_keys($data));
      
      // write out the data    
      for ($i = 0; $i < count($data['dates']); $i++) {
          $temp = array($data['dates'][$i], $data['type1'][$i], $data['type2'][$i]);
          fputcsv($fh, $temp);
      }
      

      【讨论】:

      • 感谢 Marc——这就是我会做的,但我需要它作为字符串,而不是文件。
      • @marc-- 谢谢,但我正在使用它向函数提供数据,并且不想留下数据文件(或处理清理)。
      • 在内存中打开文件而不是在磁盘上:fopen('php://memory', 'rw')
      猜你喜欢
      • 2020-06-06
      • 1970-01-01
      • 2012-01-12
      • 1970-01-01
      • 2011-07-26
      • 1970-01-01
      • 2015-12-31
      • 2013-09-12
      • 1970-01-01
      相关资源
      最近更新 更多