基于PHP中的CSV2在CSV1中查找并替换列

基于PHP中的CSV2在CSV1中查找并替换列,php,Php,我正在尝试将第一个CSV中“Close”列的值替换为第二个CSV中“LTP”列的值,其中CSV2和CSV1中的以下列应相同: “符号=符号”、“日期=时间戳”、“到期日=到期日”、“期权类型=期权类型”、“履约价格=履约价格” 以下是CSV1的当前结构: INSTRUMENT SYMBOL EXPIRY_DT STRIKE_PR OPTION_TYP OPEN HIGH LOW CLOSE SETTLE_PR CONTRACTS VAL_INLAKH OP

我正在尝试将第一个CSV中“Close”列的值替换为第二个CSV中“LTP”列的值,其中CSV2和CSV1中的以下列应相同:

“符号=符号”、“日期=时间戳”、“到期日=到期日”、“期权类型=期权类型”、“履约价格=履约价格”

以下是CSV1的当前结构:

INSTRUMENT  SYMBOL  EXPIRY_DT   STRIKE_PR   OPTION_TYP  OPEN    HIGH    LOW CLOSE   SETTLE_PR   CONTRACTS   VAL_INLAKH  OPEN_INT    CHG_IN_OI   TIMESTAMP
OPTSTK  INFY    26-Apr-18   780 CE  0   0   0   408.6   361.05  0   0   0   0   2-Apr-18
OPTSTK  INFY    26-Apr-18   800 CE  0   0   0   388.95  341.15  0   0   0   0   2-Apr-18
OPTSTK  INFY    26-Apr-18   820 CE  0   0   0   369.35  321.25  0   0   0   0   2-Apr-18
OPTSTK  INFY    26-Apr-18   840 CE  0   0   0   349.75  301.35  0   0   0   0   2-Apr-18
OPTSTK  INFY    26-Apr-18   860 CE  0   0   0   330.2   281.45  0   0   0   0   2-Apr-18
OPTSTK  INFY    26-Apr-18   880 CE  0   0   0   310.75  261.55  0   0   0   0   2-Apr-18
OPTSTK  INFY    26-Apr-18   900 CE  0   0   0   291.35  241.65  0   0   0   0   2-Apr-18
OPTSTK  INFY    26-Apr-18   920 CE  0   0   0   272.15  221.75  0   0   0   0   2-Apr-18
OPTSTK  INFY    26-Apr-18   940 CE  0   0   0   216 201.85  0   0   5400    0   2-Apr-18
OPTSTK  INFY    26-Apr-18   960 CE  0   0   0   234.45  181.95  0   0   0   0   2-Apr-18
OPTSTK  INFY    26-Apr-18   980 CE  0   0   0   216.1   162.1   0   0   0   0   2-Apr-18
OPTSTK  INFY    26-Apr-18   1000    CE  0   0   0   136 142.3   0   0   24600   0   2-Apr-18
CSV2的结构是:

Symbol   Date    Expiry  Option Type     Strike Price    Open    High    Low     Close   LTP     Settle Price    No. of contracts    Turnover in Lacs    Premium Turnover in Lacs    Open Int    Change in OI    Underlying Value
INFY    2-Apr-18    26-Apr-18   CE  780 0   0   0   408.6   0   361.05  0   0   0   0   0   1137.15
INFY    2-Apr-18    26-Apr-18   CE  1380    1   1   1   1   1   1   1   8.29    0.01    600 600 1137.15
INFY    2-Apr-18    26-Apr-18   CE  820 0   0   0   369.35  0   321.25  0   0   0   0   0   1137.15
INFY    2-Apr-18    26-Apr-18   CE  840 0   0   0   349.75  0   301.35  0   0   0   0   0   1137.15
INFY    2-Apr-18    26-Apr-18   CE  860 0   0   0   330.2   0   281.45  0   0   0   0   0   1137.15
INFY    2-Apr-18    26-Apr-18   CE  880 0   0   0   310.75  0   261.55  0   0   0   0   0   1137.15
INFY    2-Apr-18    26-Apr-18   CE  900 0   0   0   291.35  0   241.65  0   0   0   0   0   1137.15
INFY    2-Apr-18    26-Apr-18   CE  920 0   0   0   272.15  0   221.75  0   0   0   0   0   1137.15
INFY    2-Apr-18    26-Apr-18   CE  940 0   0   0   216 216 201.85  0   0   0   5400    0   1137.15
INFY    2-Apr-18    26-Apr-18   CE  960 0   0   0   234.45  0   181.95  0   0   0   0   0   1137.15
INFY    2-Apr-18    26-Apr-18   CE  980 0   0   0   216.1   0   162.1   0   0   0   0   0   1137.15
INFY    2-Apr-18    26-Apr-18   CE  1000    0   0   0   136 134 142.3   0   0   0   24600   0   1137.15
INFY    2-Apr-18    26-Apr-18   CE  1020    0   0   0   126 126 122.65  0   0   0   1200    0   1137.15

关于CSV和一般任何文件的一些事情

我正在尝试将第一个CSV中“Close”列的值替换为第二个CSV中“LTP”列的值,其中包含以下列

您不能“替换”文件中的任何内容。但是,您可以使用
fgetcsv
从文件中提取数据,然后使用
fputcsv
更改数据并使用更改后的数据写入新文件

正如您所展示的“无代码”,我不想写太多。但我只想回顾一下过程

  • 使用新值(完全)读入文件,并从中创建数组
  • 逐行读取要更改的文件
  • 对于第二个文件的每一行,在第一行(数组)中找到正确的行,并更新文件#2(您的文件#1)中该行的数据
  • 写入包含更新数据的新文件
  • 您必须读取要在最后更改数据的文件,因为您希望保留该文件中行的顺序,这样做更简单
  • 匹配数据的提示。读取文件#1时,获取需要匹配的字段,并使用md5对其进行散列。Md5的速度非常快,大约每秒500万次哈希(是的,我计时了)

    现在,这与安全或其他任何事情都没有关系,我马上会解释

    构建数组时(步骤1),获取要匹配的字段并对其进行散列,然后将其用作数组中的键

      $hash = md5(
          $row['Symbol'] .
          strtotime($row['Date']) . //convert to timestamp
          $row['Expiry'] .
          $row['Option Typ'] .
          $row['Strike Price']
      );
    
      $data[$hash] = $row;
    
    然后在读取第二个文件(要修改的文件)时执行相同的操作

    然后,在查看要修改的文件时,只需在
    $data
    数组
    isset($data[$newHash])
    中查找散列即可。一旦找到了包含这些数据的行,剩下的就很简单了

    现在读取文件的基本方法是

      $h = fopen('filename.csv', 'r');
      $data = [];
    
      $headers = false;
      while(!feof($h)){
          $row = fgetcsv($h);
          if(!$headers) $headers = $row;
    
          $row = array_combine($headers, $row);
          //do the hash "and other stuff" 
          $data[$hash] = $row;
      }
    
    然后在一个文件完成后读取另一个文件,使用相同类型的循环,进行散列,匹配所需的数据,更新旧数据,将行写入新的(第三个)文件等

    要使哈希有效,数据必须从一个CSV匹配到另一个CSV(显然),不能有重复的“哈希”行。数据的行散列相同,但在其他字段中有值。例如,如果同一文件中有两行散列相同,则
    Close
    值不同。不管怎样,这都会给你带来麻烦


    祝你好运,查阅一些关于如何处理CSV文件的教程,有很多教程。

    你看过哪些将输出数组吗?在那之后,任务相当直接。很高兴看到您尝试了什么。但我不确定这是否有效,因为两个CSV中的行数不相同,甚至没有排序。这就是我试图实现列名比较标准的原因。是我,我将在数据库表中插入一个CSV,然后循环另一个,在数据库中搜索并写入新文件。“不确定”表示您尚未尝试。考虑一下这个问题,找出每个CSV(使用
    fgetcsv
    后的数组)中需要什么以及最终修改的数组中需要什么关键点。@Tigger我同时也在考虑逻辑。但我对PHP不是很精通,所以我认为你是个不错的人。谢谢你的努力。我开始朝着同一个方向思考,但未能付诸实施。你的帖子很有帮助。当然,我在工作中一直处理CSV文件。
      $hash = md5(
          $row['Symbol'] .
          strtotime($row['Date']) . //convert to timestamp
          $row['Expiry'] .
          $row['Option Typ'] .
          $row['Strike Price']
      );
    
      $data[$hash] = $row;
    
     $newHash = md5(
          $row['SYMBOL'] .
          TIMESTAMP . //convert to timestamp
          $row['EXPIRY_DT'] .
          $row['OPTION_TYP'] .
          $row['STRIKE_PR'] .
      );
    
      $h = fopen('filename.csv', 'r');
      $data = [];
    
      $headers = false;
      while(!feof($h)){
          $row = fgetcsv($h);
          if(!$headers) $headers = $row;
    
          $row = array_combine($headers, $row);
          //do the hash "and other stuff" 
          $data[$hash] = $row;
      }