【问题标题】:Search for, and remove column from CSV file从 CSV 文件中搜索和删除列
【发布时间】:2013-08-17 15:20:35
【问题描述】:

我正在尝试编写一个包含两个参数的子例程,即 CSV 文件中的 filenamecolumn name。该子例程将搜索第二个参数(列名)并从 CSV 文件中删除该列(或多个列),然后返回已删除参数的 CSV 文件。

我觉得我已经完成了这个 sub 的前半部分(打开文件,检索标题和值),但我似乎找不到在 CSV 文件中搜索用户输入的字符串的方法并删除整列。有任何想法吗?这是我目前所拥有的。

sub remove_columns {
   my @Para = @_;
   my $args = @Para;
   die "Insufficent arguments\n" if ($nargs < 2);

   open file, $file
   $header = <file>;
   chomp $header;

   my @hdr = split ',',$header;

   while (my $line = <file>){
    chomp $line;
    my @vals = split ',',$line;

    #hash that will allow me to access column name and values quickly
    my %h;

    for (my $i=0; $i<=$#hdr;$i++){
      $h{$hdr[$i]}=$i;
    }
     ....
}

搜索和删除将在此处完成。我一直在考虑如何解决这个问题;我要修改的 CSV 文件会很大,所以速度是一个因素,但我似乎想不出一个好的方法来解决这个问题。我是 Perl 的新手,所以我有点挣扎。

【问题讨论】:

    标签: arrays perl csv


    【解决方案1】:

    这里有一些提示,希望能助您一臂之力。

    要删除数组中$index 位置的数组元素,请使用:

    splice @array,$index,1 ;
    

    由于速度是一个问题,您可能希望在开始时构造一个列号数组,然后循环数组的元素

    for my $index (@indices) {
      splice @array,$index,1 ;
    } 
    

    (这种方式比 for (my $i=0; $i&lt;=$#hdr;$i++) 类型循环更符合 Perl 的习惯)

    另一件需要考虑的事情 - CSV 格式非常复杂。您的数据可能在" " 中包含, 的数据,例如

    1,"column with a , in it" 
    

    我会考虑使用类似Text::CSV

    【讨论】:

      【解决方案2】:

      你应该看向Text::CSV的方向

      或者你可以这样做:

      my $colnum;
      my @columns = split(/,/, <$file>);
      for(my $i = 0; $i < scalar(@columns); $i++) {
          if($columns[$i] =~ /^$unwanted_column_name$/) {
               $colnum = $i;
               last;
          };
      };
      
      while(<$file>) {
         my @row = split(/,/, $_);
         splice(@row, $colnum, 1);
         #do something with resulting array @row
      };
      

      旁注: 你真的应该使用strictwarnings

      split(/,/, <$file>);
      

      不适用于所有 CSV 文件

      【讨论】:

        【解决方案3】:

        有一种优雅的方法可以从数组中删除一些列。如果我在数组@cols 中有要删除的列,在@headers 中有标题,我可以制作要保留的索引数组:

        my %to_delete;
        @to_delete{@cols} = ();
        my @idxs = grep !exists $to_delete{$headers[$_]}, 0 .. $#headers;
        

        然后很容易制作新的标题

        @headers[@idxs]
        

        还有来自读取列的新行

        @columns[@idxs]
        

        同样的方法可以用于例如重新排列数组。如何执行此类任务是非常快速且非常惯用的 Perl 方式。

        【讨论】:

          猜你喜欢
          • 2015-02-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-02
          • 2010-11-26
          • 2021-07-16
          相关资源
          最近更新 更多