我有两个CSV文件,我想与Perl进行比较。
我有使用Text::CSV::Slurp将文件导入Perl的代码,它为文件提供了一个很好的哈希引用数组。
使用Data::Dumper::Concise正确地显示了我所有的数据导入。
use strict;
use warnings;
use Text::CSV::Slurp;
use Data::Dumper::Concise;
my $file1_src = "IPB-CSV.csv";
my $file2_src = "SRM-CSV.csv";
my $IPB = Text::CSV::Slurp->load(file => $file1_src);
my $SRM = Text::CSV::Slurp->load(file => $file2_src);
print Dumper($IPB);
print Dumper($SRM);转储的结果如下所示
$IPB
[
{
Drawing => "1001"
},
{
Drawing => "1002"
},
{
Drawing => "1003"
}
]$SRM
[
{
Drawing => "1001",
Figure => "Figure 2-8",
Index => 2,
Nomenclature => "Some Part"
},
{
Drawing => "1002",
Figure => "Figure 2-8",
Index => 2,
Nomenclature => "Some Part"
},
{
Drawing => "2001",
Figure => "Figure 2-8",
Index => 2,
Nomenclature => "Some Part"
},
{
Drawing => "2002",
Figure => "Figure 2-8",
Index => 2,
Nomenclature => "Some Part"
}
]我想根据每个散列的Drawing键比较这两个数组,并创建两个CSV文件,如下所示
$IPB中的项,但不包含$SRM中的项,只包含‘`Drawing列中的数据。$SRM中,而不是$IPB中,包含与Drawing列相关的所有字段。我已经找到了很多信息来比较文件,看看它们是否匹配,或者比较散列或数组中的单个数据,但是我找不到特定于我所需要的东西。
发布于 2014-04-28 22:50:22
这个简短的程序为$ipb和$srm使用示例值,并创建我认为您想要的输出。(除了包名之类的全局标识符之外,请不要使用大写字母。)
有几个问题
Text::CSV::Slurp将为您留下两个哈希数组,如果没有进一步的索引,这些哈希数组对此任务没有任何用处。通过逐行处理文件,从头开始创建适当的数据结构会好得多。Drawing键相关的所有信息,但是,由于Perl散列本身是无序的,所以Text::CSV::Slurp丢失了字段名的顺序。最好的方法是按发现的任何顺序打印数据,但前面是显示字段名的标题行。这是避免Text::CSV::Slurp的另一个原因
use strict;
use warnings;
use autodie;
# The original data
my $ipb = [{ Drawing => 1001 }, { Drawing => 1002 }, { Drawing => 1003 }];
my $srm = [
{
Drawing => "1001",
Figure => "Figure 2-8",
Index => 2,
Nomenclature => "Some Part"
},
{
Drawing => "1002",
Figure => "Figure 2-8",
Index => 2,
Nomenclature => "Some Part"
},
{
Drawing => "2001",
Figure => "Figure 2-8",
Index => 2,
Nomenclature => "Some Part"
},
{
Drawing => "2002",
Figure => "Figure 2-8",
Index => 2,
Nomenclature => "Some Part"
}
];
# Index the data
my %srm;
for my $item (@$srm) {
my $drawing = $item->{Drawing};
$srm{$drawing} = $item;
}
my %ipb;
for my $item (@$ipb) {
my $drawing = $item->{Drawing};
$ipb{$drawing} = 1;
}
# Create the output files
open my $csv1, '>', 'file1.csv';
for my $id (sort keys %ipb) {
next if $srm{$id};
print $csv1 $id, "\n";
}
close $csv1;
open my $csv2, '>', 'file2.csv';
my @keys = keys %{ $srm->[0] };
print $csv2 join(',', @keys), "\n";
for my $id (sort keys %srm) {
next if $ipb{$id};
print $csv2 join(',', @{$srm{$id}}{@keys}), "\n";
}
close $csv2;输出
file1.csv
1003file2.csv
Drawing,Nomenclature,Index,Figure
2001,Some Part,2,Figure 2-8
2002,Some Part,2,Figure 2-8发布于 2014-04-28 20:13:34
既然绘图是一种排序标准,为什么不将数据“索引”成一些更方便的东西,其中绘图索引是关键,相应的数据是相应的值?
my %ipb;
for my $record ( @$IPB ) {
my $index = $record->{Drawing};
push @{ $ipb{$index} }, $record;
}
my %srm;
for my $record ( @$SRM ) {
my $index = $record->{Drawing};
push @{ $srm{$index} }, $record;
}现在,找出$IPB和$SRM特有的索引应该是轻而易举的。
use List::MoreUtils 'uniq';
my @unique_ipb = uniq( grep { $ipb{$_} and not $srm{$_} } keys( %ipb ), keys( %srm ) );
my @unique_srm = uniq( grep { $srm{$_} and not $ipb{$_} } keys( %ipb ), keys( %srm ) );两者有什么共同之处?
my @intersect = uniq( grep { $srm{$_} and $ipb{$_} } keys( %ipb ), keys( %srm ) );绘制索引1002的所有图形编号是多少?
print $_->{Figure}, "\n" for @{ $ipb{1002} // [] }, @{ $srm{1002} // [] };发布于 2014-04-28 20:14:19
这有点复杂,因为您的数据结构不太适合进行比较。您有对散列引用数组的引用,并且关心hashref键中的数据。我的第一步是将IPB扁平化为一个数组(因为在这个数组中没有数据),并将SRM转换为一个单独的hashref。
my @ipbarray = map { ${$_}{Drawing} } $IPB; # Creates an array from IPB.
my $srmhash = {};
for my $hash ($SRM) {
${$srmhash}{${$hash}{Drawing}} = $hash unless defined ${$srmhash}{${$hash}{Drawing}}; # Don't overwrite if it exists
}现在我们有了更多可行的数据结构。
下一步是对比这些值:
my @ipbonly = ();
my @srmonly = ();
for my $ipbitem (@ipbarray) {
push @ipbonly, ( Drawing => $ipbitem } unless defined ${$srmhash}{$ipbtem};
}
for my $srmitem (keys $srmhash) {
push @srmonly, ${$srmhash}{$srmitem} unless grep { $_ == $srmitem } @ipbarray;
}此时,@ipbonly和@srmonly将包含所需的数据。
https://stackoverflow.com/questions/23349773
复制相似问题