Arrays 将两个文件中的哈希值合并到一个文件中

Arrays 将两个文件中的哈希值合并到一个文件中,arrays,perl,hash,push,dereference,Arrays,Perl,Hash,Push,Dereference,我有两个包含如下数据的文件: 1 0.9 2 0.6 3 0.4 ... 2 0.7 1 0.6 3 0.2 ... 文件1包含组号(第一列)和切换另一组(第二列)的频率(第三列): 文件1: 1 2 0.6 2 1 0.6 3 1 0.4 1 3 0.4 2 3 0.2 等等 文件2包含组号(第一列)及其出现频率(第二列) 文件2: 1 0.9 2 0.7 3 0.5 等等 我想创建另一个包含FILE2的文件,其中FILE1的每个开关的值如下: 1 0.9 2 0.6 3 0.4 ..

我有两个包含如下数据的文件:

1 0.9 2 0.6 3 0.4 ...
2 0.7 1 0.6 3 0.2 ...
文件1包含组号(第一列)和切换另一组(第二列)的频率(第三列):

文件1:

1 2 0.6 
2 1 0.6
3 1 0.4
1 3 0.4
2 3 0.2
等等

文件2包含组号(第一列)及其出现频率(第二列)

文件2:

1 0.9
2 0.7
3 0.5
等等

我想创建另一个包含FILE2的文件,其中FILE1的每个开关的值如下:

1 0.9 2 0.6 3 0.4 ...
2 0.7 1 0.6 3 0.2 ...
基本上,我希望第一列是组号,第二列是它出现的频率,然后是他们切换到的组和该切换的频率,然后下一个切换都在同一行中,对于那个特定的组,然后下一行-组2等等

所以我想读入FILE1,对每个组的数组进行散列,其中键是组号,值是它们切换到的组,以及切换的频率。我将为每组设置一个大数组,其中包含它们切换到的每个组的子数组和频率。然后我想用与第一个散列中相同的键创建另一个散列,但要使用FILE2第一列中的数字和FILE2第二列中的值。然后我将打印出“hash2键hash2值hash1该键的整个数组”。这是我使用Perl的尝试:

#!/usr/bin/perl -W

$input1= $ARGV[0];
$input2 = $ARGV[1];
$output = $ARGV[2];

%switches=();

open (IN1, "$input1");
while (<IN1>) {
 @tmp = split (/\s+/, $_);
 chomp @tmp;
 $group = shift @tmp;
 $switches{$group} = [@tmp];

 push (@{$switches{$group}}, [@tmp]);

}

close IN1;

%groups=();

open (IN2, "$input2");
while (<IN2>) {
 chomp $_;
 ($group, $pop) = split (/\s+/, $_);
 $groups{$group} = $pop;
}
close IN2;

open (OUT, ">$output");

foreach $group (keys %groups) {
  print OUT "$group $pop @{$switches{$group}}\n"
}

close OUT;
所以基本上:

组“最后一个频率编号”该组切换到类似smth阵列的“最后一个开关频率”的最后一个组(0x100832330)

我假设我在FILE1中将所有开关推入数组的散列中是做错了smth,并且在打印输出时在末尾取消引用也是做错了

请帮忙,
谢谢

您的
%开关
哈希包含冗余信息;只需使用
按钮
。另外,你需要做更多的工作来打印出你想要的。以下是您的代码,仅做了少量更改:

$input1= $ARGV[0];
$input2 = $ARGV[1];
$output = $ARGV[2];

%switches=();

open (IN1, "$input1");
while (<IN1>) {
 @tmp = split (/\s+/, $_);
 chomp @tmp;
 $group = shift @tmp;

 push (@{$switches{$group}}, [@tmp]);

}

close IN1;

%groups=();

open (IN2, "$input2");
while (<IN2>) {
 chomp $_;
 ($group, $pop) = split (/\s+/, $_);
 $groups{$group} = $pop;
}
close IN2;

open (OUT, ">$output");

foreach $group (sort {$a <=> $b} keys %groups) {
    print OUT "$group $groups{$group} ";
    for my $aref (@{$switches{$group}}) {
        print OUT "@{$aref}";
    }
    print OUT "\n";
}

close OUT;


__END__


1 0.9 2 0.63 0.4
2 0.7 1 0.63 0.2
3 0.5 1 0.4
$input1=$ARGV[0];
$input2=$ARGV[1];
$output=$ARGV[2];
%开关=();
打开(IN1,“$input1”);
而(){
@tmp=拆分(/\s+/,$);
chomp@tmp;
$group=shift@tmp;
push(@{$switches{$group},[@tmp]);
}
接近1;
%组=();
打开(IN2,“$input2”);
而(){
大口大口;
($group,$pop)=拆分(/\s+/,$);
$groups{$group}=$pop;
}
接近2;
打开(输出“>$output”);
foreach$组(排序{$a$b}键%groups){
打印出“$group$groups{$group}”;
对于我的$aref(@{$switches{$group}){
打印“@{$aref}”;
}
打印出“\n”;
}
收尾;
__结束__
1 0.9 2 0.63 0.4
2 0.7 1 0.63 0.2
3 0.5 1 0.4

另请参见和

,因为每列表示有价值的内容,而不是数组,所以您应该将数据存储在更详细的结构中。您可以通过以下方式完成此操作

引用是指向另一个数据结构的指针。例如,您可以将组存储在散列中。但是,每个哈希值不是包含一组由空格分隔的数字,而是指向包含该组数据点的数组。并且,该数组中的这些数据点中的每一个都指向一个散列,该散列的键是
SWITCH
,表示它们的切换,而
FREQ
表示它们的频率

您可以将组1的第一个数据点的频率描述为:

$data{1}->[0]->{FREQ};
通过这种方式,您可以更轻松地操作数据——即使您只是将其重写到另一个平面文件中。您还可以使用模块以保存其结构的方式写入数据

#! /usr/bin/env perl
#
use strict;
use feature qw(say);
use autodie;
use warnings;
use Data::Dumper;

use constant {
    FILE1       => "file1.txt",
    FILE2       => "file2.txt",
};

my %data;  # A hash of an array of hashes (superfun!)

open my $fh1, "<", FILE1;

while ( my $line = <$fh1> ) {
    chomp $line;
    my ( $group, $switch, $frequency ) = split /\s+/, $line;
    if ( not exists $data{$group} ) {
        $data{$group} = [];
    }
    push @{ $data{$group} }, { SWITCH => $switch, FREQ => $frequency };
}
close $fh1;

open my $fh2, "<", FILE2;
while ( my $line = <$fh2> ) {
    chomp $line;
    my ( $group, $frequency ) = split /\s+/, $line;
    if ( not exists $data{$group} ) {
        $data{$group} = [];
    }
    push @{ $data{$group} }, { SWITCH => undef, FREQ => $frequency };
}
close $fh2;
say Dumper \%data;

这会满足你的需要

我为缺乏分析而道歉,但是已经很晚了,我应该上床睡觉了

我希望这有帮助

use strict;
use warnings;

my $fh;
my %switches;

open $fh, '<', 'file1.txt' or die $!;
while (<$fh>) {
  my ($origin, @switch) = split;
  push @{ $switches{$origin} }, \@switch;
}

open $fh, '<', 'file2.txt' or die $!;
while (<$fh>) {
  my ($origin, $freq) = split;
  my $switches = join ' ', map join(' ', @$_), @{ $switches{$origin} };
  print join(' ', $origin, $freq, $switches), "\n";
}

更新

这里是您自己的代码的固定版本,可以产生类似的结果。主要问题是
%中的值切换数组的数组,因此必须进行两次解引用。我通过添加
@switches
,修复了这个问题,它包含与当前
%switches
值相同的内容,但用字符串代替了两个元素数组

我还添加了
使用严格
使用警告
,并正确声明了所有变量。
open
调用已更改为三个参数
open
,并使用词汇文件句柄,现在正在检查它们是否成功。我已经更改了您的
split
调用,因为您只需要一个没有参数的简单的裸
split
。我已经删除了你的
@tmp
,并使用了正确的列表分配。哦,我已经将浪费的
[@array]
更改为一个简单的
\@array
(如果不使用
my
声明变量,它将无法工作)

我仍然认为我的版本更好,如果只是因为它要短得多,而你的版本以随机顺序打印组

#!/usr/bin/perl

use strict;
use warnings;

my ($input1, $input2, $output) = @ARGV;

my %switches;

open my $in1, '<', $input1 or die $!;
while (<$in1>) {
  my ($group, @switches) = split;
  push @{ $switches{$group} }, \@switches;
}

close $in1;

my %groups;

open my $in2, '<', $input2 or die $!;
while (<$in2>) {
 my ($group, $pop) = split;
 $groups{$group} = $pop;
}
close $in2;

open my $out, '>', $output or die $!;
for my $group (keys %groups) {
  my $pop = $groups{$group};
  my @switches = map "@$_", @{ $switches{$group} };
  print $out "$group $pop @switches\n"
}
close $out or die $!;
#/usr/bin/perl
严格使用;
使用警告;
my($input1,$input2,$output)=@ARGV;
我的%开关;
打开我的$in1、、$output或die$!;
对于我的$组(键%groups){
my$pop=$groups{$groups};
我的@switches=map“@$\”,@{$switches{$group};
打印$out“$group$pop@switches\n”
}
关闭$或死亡$!;

请在编写的每个Perl程序开始时始终
使用strict
使用warnings
。它将使您避免许多简单的错误,尤其是在您请求代码帮助时。请不要避免
split/\s+/
。您想要的是
拆分“”
,或者,如果您要拆分
$\ucode>,则只需
拆分就可以了。“您应该将数据存储在更详细的结构中”是一个奇怪的注释,当OP使用数组的散列
%开关
和另一个简单的散列
%组
时。
1 0.9 2 0.6 3 0.4
2 0.7 1 0.6 3 0.2
3 0.5 1 0.4
#!/usr/bin/perl

use strict;
use warnings;

my ($input1, $input2, $output) = @ARGV;

my %switches;

open my $in1, '<', $input1 or die $!;
while (<$in1>) {
  my ($group, @switches) = split;
  push @{ $switches{$group} }, \@switches;
}

close $in1;

my %groups;

open my $in2, '<', $input2 or die $!;
while (<$in2>) {
 my ($group, $pop) = split;
 $groups{$group} = $pop;
}
close $in2;

open my $out, '>', $output or die $!;
for my $group (keys %groups) {
  my $pop = $groups{$group};
  my @switches = map "@$_", @{ $switches{$group} };
  print $out "$group $pop @switches\n"
}
close $out or die $!;