根据公共字段匹配和合并csv数据字段

时间:2019-05-11 21:50:03

标签: php

我需要读取2个CSV文件数据,合并标题并删除重复的标题。然后,我需要将数据添加到相应的标头中,如果文件中没有标头的数据,则默认为空。

For example:

File one:
'Name', 'Surname', 'Address'
'John', 'Doe',     'example st 123'

File two:
'Surname', 'City', 'Gender'
'Doe',     'Riga',  'Male'

Output File:
'Name', 'Surname', 'Address', 'City', 'Gender'
'John', 'Doe','example st 123', ' ',   ' '
' ',    'Doe',        ' ',    'Riga', 'Male'

到目前为止,我已经制作了一个给我这些数组的类:

array(5) {
  [0]=>
  string(4) "Name"
  [1]=>
  string(7) "Surname"
  [2]=>
  string(7) "Address"
  [4]=>
  string(4) "City"
  [5]=>
  string(6) "Gender"
}
array(2) {
  [0]=>
  array(1) {
    [1]=>
    array(3) {
      [0]=>
      string(4) "John"
      [1]=>
      string(3) "Doe"
      [2]=>
      string(10) "Street 123"
    }
  }
  [1]=>
  array(1) {
    [1]=>
    array(3) {
      [0]=>
      string(3) "Doe"
      [1]=>
      string(4) "Riga"
      [2]=>
      string(4) "Male"
    }
  }
}

这是通过此类完成的:

class Reader
{
    private $filePaths = [];
    private $headers = [];
    private $data = [];

    public function add(string $filePath): void
    {
        $this->filePaths[] = $filePath;
    }
    public function read(): void
    {
        foreach ($this->filePaths as $filePath) {

            $getData = array_map('str_getcsv', file($filePath));

            $this->headers = array_unique(array_merge($this->headers, $getData[0]));

            unset($getData[0]);

            $this->data[] = $getData;
        }
    }

    public function getData(): array
    {
        return $this->data;
    }

    public function getHeaders(): array
    {
        return $this->headers;
    }

任何人都可以帮助我了解如何格式化数据以获得预期结果吗?

目前,我所能得到的就是这个:

Name,Surname,Address,City,Gender
John,Doe,"Street 123"
Doe,Riga,Male

1 个答案:

答案 0 :(得分:1)

这是我的解决方法

class Reader
{
    public $filePaths = [];
    private $headers = [];
    private $data = [];

    private $originalHeaders = [

    ];

    public function add(string $filePath): void
    {
        $this->filePaths[] = $filePath;
    }
    public function read(): void
    {
        foreach ($this->filePaths as $filePath) {
            $fp = fopen($filePath, 'r');

            $h = fgetcsv($fp);
            $this->originalHeaders[] = $h;
            fclose($fp);
            $this->headers = array_unique(array_merge($this->headers, $h));
        }
        print_r($this->originalHeaders);
        print_r($this->headers);


        $i = 0; // so we know which file we are processing
        foreach ($this->filePaths as $i => $filePath) {
            $getData = array_map('str_getcsv', file($filePath));
            unset($getData[0]);

            $this->data = array_merge($this->data, $this->mapData($i, $getData));
        }
        print_r($this->data);
    }
    public function output($filename)
    {
        $fp = fopen($filename, 'w');
        fputcsv($fp, $this->headers);
        foreach ($this->data as $row) {
            fputcsv($fp, $row);
        }
        fclose($fp);
    }


    /**
     * Map data in column i to column j
     */
    private function mapData($n, $data) : array
    {
        $inputColumns = $this->originalHeaders[$n];
        $outputColumns = $this->headers;
        $columnIndex = array_flip($outputColumns);
        $mappedData = [];
        foreach( $data as $i => $row ) {
            $workData = array_fill(0, count($this->headers), '');
            // Now take each input data and put it in the right place
            foreach ($row as $j => $value) {
                // Get name of source column
                $sourceColumn = $inputColumns[$j];
                // Where does that data go in the output
                $targetColumnIndex = $columnIndex[$sourceColumn];
                // Put the data there
                $workData[$targetColumnIndex] = $value;
            }
            // Store it in the mapped data
            $mappedData[] = $workData;
        }
        return $mappedData;
    }

    public function getData(): array
    {
        return $this->data;
    }

    public function getHeaders(): array
    {
        return $this->headers;
    }
}

$r = new Reader();
$r->filePaths = ['file1.csv', 'file2.csv'];
$r->read();

输入1

Name,Surname,Address
John,Doe,"example st 123"
Natalie,Portman,"1 Starway Ave"
Scotty,Clarke,"Some street Mississippi"

输入2

Surname,City,Gender
Doe,Riga,Male
Ford,"Los Angeles",Male

输出

Name,Surname,Address,City,Gender
John,Doe,"example st 123",,
Natalie,Portman,"1 Starway Ave",,
Scotty,Clarke,"Some street Mississippi",,
,Doe,,,Riga,Male
,Ford,,,"Los Angeles",Male