我有一个带有多行的csv文件,其中第一个字段是重复的,而从其他字段只有一行实际填充(并且总是不同) 我需要编写一个将这些行合并为一个的perl CGI csv文件类似于下面的示例
aaaa,3
aaaa,,5
aaaa,,,1
aaaa,,,,3
bb,2
bb,,4
bb,,,,,,,,,,6
cc,,,,,,5
dd,5
我想要输出的内容应该是:
aaaa,3,5,1,3
bb,2,4,,,,,,,,6
cc,,,,,,5
dd,5
我对perl语言很新,但是从我做过的一些研究中我认为使用哈希似乎是要走的路,但我仍然没有完全了解这些是如何工作的,请记住我需要在perl cgi中使用它,所以一个命令行不会帮助我
所以我从另一篇帖子here
中抓取这段代码open my $ifh, '<', "input_file" or die $!;
open my $ofh, '>', "output_file" or die $!;
while (<$ifh>) {
chomp;
my @F = split /,/;
my $key = shift @F;
push @{$hash{$key}}, @F;
}
foreach (sort keys %hash) {
print $ofh "$_," . join (',', @{$hash{$_}}) . "\n";
}
close $ifh;
close $ofh;
但它只是在重复的同一行添加字段,我需要在实际的未定义字段中写入
答案 0 :(得分:3)
关于合并来自不同行的值的一点对我感兴趣,足以让我们去了解它。这就是我所做的。其他人可能能够改善我的解决方案。
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
1<input type="checkbox" class="checkoption" /> 2
<input type="checkbox" class="checkoption" /> 3
<input type="checkbox" class="checkoption" /> 4
<input type="checkbox" class="checkoption" /> everything
<input type="checkbox" class="checkoption" id="everythingbox" checked/>
我得到的输出是:
#!/usr/bin/perl
use strict;
use warnings;
use feature 'say';
my %data;
while (<DATA>) {
chomp;
my ($key, @values) = split /,/;
if ($data{$key}) {
# It seems we can be sure that the new value
# we're adding will be the last element on the line.
$data{$key}[$#values] = $values[$#values];
} else {
$data{$key} = \@values;
}
}
for my $k (sort keys %data) {
say join ',', $k, map { $_ // '' } @{$data{$k}};
}
__DATA__
aaaa,3
aaaa,,5
aaaa,,,1
aaaa,,,,3
bb,2
bb,,4
bb,,,,,,,,,,6
cc,,,,,,5
dd,5
将此转换为使用CGI进行输入和输出留给读者练习: - )
答案 1 :(得分:2)
answer from Dave Cross 非常好,但它依赖于每一行数据比同一密钥的所有数据都长,这不是你的问题所确定的
这是一个非常类似的程序来修复它,并且还跟踪键在源数据中出现的顺序,以便它可以在输出上再现
该程序期望输入CSV文件的路径作为命令行上的参数,并将输出打印到STDOUT。您可以在命令行上重定向输出
将此作为CGI应用程序编写是一个非常广泛的问题。如果你遇到困难,你需要尽你所能并在这里询问具体的问题
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
...
ipaddress = models.CharField(default="0.0.0.0", max_length=30)
use strict;
use warnings 'all';
my ( @keys, %data );
while ( <> ) {
next unless /\S/;
chomp;
my @newline = split /,/;
my $key = $newline[0];
if ( my $line = $data{ $key } ) { # Update any previously-blank fields
for my $i ( 0 .. $#newline ) {
$line->[$i] = $newline[$i] unless length $line->[$i] // '';
}
}
else { # Build the first instance of this key
$data{ $key } = \@newline;
push @keys, $key;
}
}
print join( ',', @{ $data{$_} } ), "\n" for @keys;
答案 2 :(得分:0)
我会像这样修改你的代码:
$#F
(0..$#F)
是最后一个元素的数组地址,因此$hash{$key}
是@F中地址的范围。这允许您将@F中的元素分配到另一个数组的相同地址(在这种情况下,${$hash{$key}}[$i]
是一个匿名数组,也就是一个arrayref,$hash{$key}->[$i] //= $F[$i]
访问该数组的$ i元素)
{{1}}表示只有在尚未定义元素的情况下才会分配。