如何复制and/or 重新分配多维数组中的数组元素?
How to replicate and/or reassign array elements in a multi-dimensional array?
代码在循环中的某处变得混乱!请帮我解决一下。
详情
复制and/or 使用引用元素重新分配多维数组中的大部分数组元素。
File-1: 数组索引列表&原数组中需要维护的元素。
File-2:原始多维数组,需要用上述信息重写。除了上面的元素,其余所有元素都必须重新分配。
File-3:预期输出(重新分配的数组元素)
注意:除file1的数组索引外,其余所有索引将替换为参考线。参考线通常出现在数组的第一行。
修改后的数组中,不需要参考线。
文件-1:
ID1 2 E1,E4
ID2 5 E6,E7,E9
ID3 1 E3
文件-2:
ID1.txt
Ref K L M N O P A B C D
E1 S H G U S K R E K K
E2 S L G N O P A B C D
E3 S L G N O P A B C D
E4 U L G G O P A B C D
E5 U L M G O P A J C D
E6 U L M G O P A J C D
E7 U L M G O P A J C D
E8 U L M G O P A J C D
E9 S L M N O P A J C D
E10 S L M N O P A J C D
.
.
.
文件 3:预期输出
new_ID1.txt
E1 K L G N O P A B C D
E2 K L M N O P A B C D
E3 K L M N O P A B C D
E4 K L G N O P A B C D
E5 K L M N O P A B C D
E6 K L M N O P A B C D
E7 K L M N O P A B C D
E8 K L M N O P A B C D
E9 K L M N O P A B C D
E10 K L M N O P A B C D
.
.
.
在预期的输出 (new_ID1.txt) 中,"E1" 和 "E4" 的数组的第二个索引是从原始数组维护的。其他所有内容均由 "E2,E3,E5...".
中的参考线替换
代码
#!/usr/bin/perl
use strict;
use warnings;
my %HoHoA = ();
open(IN,"ids.txt");
my @ids = <IN>; chomp @ids; close IN;
open(IN2,"indices_and_values.txt");
while(my $l = <IN2>)
{
chomp $l;
my @tmp = split "\t", $l;
my $lid = $tmp[0];
my $pos = $tmp[1];
my @gps = @tmp[2..$#tmp];
foreach my $g (@gps)
{
push @{$HoHoA{$lid}{$g}}, $pos;
}
}
close IN2;
foreach my $outer (sort keys %HoHoA)
{
open(IN3,"$outer.txt");
my @rS = <IN3>; chomp @rS; close IN3;
my @orgArr = (); my @refArr = (); my @newArr = ();
foreach my $unk (@rS)
{
@orgArr = split "\t", $unk;
if($unk =~ /^Ref/)
{
@refArr = split "\t", $unk;
next;
}
foreach my $inner (sort keys %{$HoHoA{$outer}})
{
if($inner =~ /^$orgArr[0]/)
{
foreach my $ele (sort {$a <=> $b} @{$HoHoA{$outer}{$inner}})
{
$refArr[$ele] = $orgArr[$ele];
}
}
#else
#{
#}
}
print ">$orgArr[0]\t";
print join("\t",@refArr[1..$#refArr]);
print "\n";
}
@rS = ();
print "\n";
}
显示的代码是好的,但有点太复杂了;您可能在处理嵌套数据结构时迷路了。这是另一种更简单的方法。
将 "reference" 文件 (File-1
) 中的信息解析为散列 (E1 => [2, ...], ..)
。我将数据的索引放在一个 arrayref 中,以允许一行有多个索引。然后逐行进行,为具有键的行替换这些索引处的数据,然后打印输出。
use warnings;
use strict;
use feature 'say';
my ($ref_file, $data_file) = @ARGV;
die "Usage: [=10=] ref-file data-file\n" if not $ref_file or not $data_file;
open my $fh, '<', $ref_file or die "Can't open $ref_file: $!";
my %rows;
while (<$fh>) {
my (undef, $idx, $row_id) = split;
for (split /,/, $row_id) {
push @{$rows{$_}}, $idx; # elem => [ indices ]
}
}
my $outfile = 'new_' . $data_file;
open $fh, '<', $data_file or die "Can't open $data_file: $!";
open my $fh_out, '>', $outfile or die "Can't open $outfile: $!";
my @ref = split ' ', <$fh>;
shift @ref; # toss the first field
while (<$fh>) {
my ($row_id, @data) = split;
if (exists $rows{$row_id}) { # this row needs attention
my @new_row = @ref;
foreach my $idx (@{$rows{$row_id}}) { # keep data at these indices
$new_row[$idx] = $data[$idx];
}
say $fh_out join "\t", $row_id, @new_row;
}
else { # use whole reference line
say $fh_out join "\t", $row_id, @ref;
}
}
新文件(为了便于阅读,显示了两个空格而不是实际的制表符)
E1 K L G N O P A B C D
E2 K L M N O P A B C D
E3 K L M N O P A B C D
E4 K L G N O P A B C D
E5 K L M N O P A B C D
E6 K L M N O P A B C D
E7 K L M N O P A B C D
E8 K L M N O P A B C D
E9 K L M N O P A B C D
E10 K L M N O P A B C D
请注意,给定的输入文件恰好具有与参考线相同的条目,用于替换许多感兴趣的索引——因此我们在上面的输出中看不到那些 "changes"。 (我通过更改输入文件进行测试以便能够看到。)
这是一种方法,如果我正确理解了你的问题陈述:
#!/usr/bin/perl
use strict;
use warnings;
my %keep_idx;
open FILE, "file-1" or die "Couldn't open file-1";
while(<FILE>) {
my (undef, $idx, $id_str) = split /\s+/;
my @ids = split /,/, $id_str;
foreach my $id (@ids) {
$keep_idx{$id}{$idx} = 1;
}
}
close FILE;
open FILE, "file-2" or die "Couldn't open file-2";
open OUTFILE, ">file-3" or die "Couldn't open file-3";
my (undef, @ref) = split /\s+/, <FILE>;
while(<FILE>) {
my ($id, @src) = split /\s+/;
my $line = "$id";
for (my $i = 0; $i <= $#src; $i++) {
my $e = $keep_idx{$id}{$i} ? $src[$i] : $ref[$i];
$line .= " $e";
}
print OUTFILE "$line\n";
}
close OUTFILE;
close FILE;
代码在循环中的某处变得混乱!请帮我解决一下。
详情
复制and/or 使用引用元素重新分配多维数组中的大部分数组元素。
File-1: 数组索引列表&原数组中需要维护的元素。
File-2:原始多维数组,需要用上述信息重写。除了上面的元素,其余所有元素都必须重新分配。
File-3:预期输出(重新分配的数组元素)
注意:除file1的数组索引外,其余所有索引将替换为参考线。参考线通常出现在数组的第一行。
修改后的数组中,不需要参考线。
文件-1:
ID1 2 E1,E4
ID2 5 E6,E7,E9
ID3 1 E3
文件-2:
ID1.txt
Ref K L M N O P A B C D
E1 S H G U S K R E K K
E2 S L G N O P A B C D
E3 S L G N O P A B C D
E4 U L G G O P A B C D
E5 U L M G O P A J C D
E6 U L M G O P A J C D
E7 U L M G O P A J C D
E8 U L M G O P A J C D
E9 S L M N O P A J C D
E10 S L M N O P A J C D
.
.
.
文件 3:预期输出
new_ID1.txt
E1 K L G N O P A B C D
E2 K L M N O P A B C D
E3 K L M N O P A B C D
E4 K L G N O P A B C D
E5 K L M N O P A B C D
E6 K L M N O P A B C D
E7 K L M N O P A B C D
E8 K L M N O P A B C D
E9 K L M N O P A B C D
E10 K L M N O P A B C D
.
.
.
在预期的输出 (new_ID1.txt) 中,"E1" 和 "E4" 的数组的第二个索引是从原始数组维护的。其他所有内容均由 "E2,E3,E5...".
中的参考线替换代码
#!/usr/bin/perl
use strict;
use warnings;
my %HoHoA = ();
open(IN,"ids.txt");
my @ids = <IN>; chomp @ids; close IN;
open(IN2,"indices_and_values.txt");
while(my $l = <IN2>)
{
chomp $l;
my @tmp = split "\t", $l;
my $lid = $tmp[0];
my $pos = $tmp[1];
my @gps = @tmp[2..$#tmp];
foreach my $g (@gps)
{
push @{$HoHoA{$lid}{$g}}, $pos;
}
}
close IN2;
foreach my $outer (sort keys %HoHoA)
{
open(IN3,"$outer.txt");
my @rS = <IN3>; chomp @rS; close IN3;
my @orgArr = (); my @refArr = (); my @newArr = ();
foreach my $unk (@rS)
{
@orgArr = split "\t", $unk;
if($unk =~ /^Ref/)
{
@refArr = split "\t", $unk;
next;
}
foreach my $inner (sort keys %{$HoHoA{$outer}})
{
if($inner =~ /^$orgArr[0]/)
{
foreach my $ele (sort {$a <=> $b} @{$HoHoA{$outer}{$inner}})
{
$refArr[$ele] = $orgArr[$ele];
}
}
#else
#{
#}
}
print ">$orgArr[0]\t";
print join("\t",@refArr[1..$#refArr]);
print "\n";
}
@rS = ();
print "\n";
}
显示的代码是好的,但有点太复杂了;您可能在处理嵌套数据结构时迷路了。这是另一种更简单的方法。
将 "reference" 文件 (File-1
) 中的信息解析为散列 (E1 => [2, ...], ..)
。我将数据的索引放在一个 arrayref 中,以允许一行有多个索引。然后逐行进行,为具有键的行替换这些索引处的数据,然后打印输出。
use warnings;
use strict;
use feature 'say';
my ($ref_file, $data_file) = @ARGV;
die "Usage: [=10=] ref-file data-file\n" if not $ref_file or not $data_file;
open my $fh, '<', $ref_file or die "Can't open $ref_file: $!";
my %rows;
while (<$fh>) {
my (undef, $idx, $row_id) = split;
for (split /,/, $row_id) {
push @{$rows{$_}}, $idx; # elem => [ indices ]
}
}
my $outfile = 'new_' . $data_file;
open $fh, '<', $data_file or die "Can't open $data_file: $!";
open my $fh_out, '>', $outfile or die "Can't open $outfile: $!";
my @ref = split ' ', <$fh>;
shift @ref; # toss the first field
while (<$fh>) {
my ($row_id, @data) = split;
if (exists $rows{$row_id}) { # this row needs attention
my @new_row = @ref;
foreach my $idx (@{$rows{$row_id}}) { # keep data at these indices
$new_row[$idx] = $data[$idx];
}
say $fh_out join "\t", $row_id, @new_row;
}
else { # use whole reference line
say $fh_out join "\t", $row_id, @ref;
}
}
新文件(为了便于阅读,显示了两个空格而不是实际的制表符)
E1 K L G N O P A B C D E2 K L M N O P A B C D E3 K L M N O P A B C D E4 K L G N O P A B C D E5 K L M N O P A B C D E6 K L M N O P A B C D E7 K L M N O P A B C D E8 K L M N O P A B C D E9 K L M N O P A B C D E10 K L M N O P A B C D
请注意,给定的输入文件恰好具有与参考线相同的条目,用于替换许多感兴趣的索引——因此我们在上面的输出中看不到那些 "changes"。 (我通过更改输入文件进行测试以便能够看到。)
这是一种方法,如果我正确理解了你的问题陈述:
#!/usr/bin/perl
use strict;
use warnings;
my %keep_idx;
open FILE, "file-1" or die "Couldn't open file-1";
while(<FILE>) {
my (undef, $idx, $id_str) = split /\s+/;
my @ids = split /,/, $id_str;
foreach my $id (@ids) {
$keep_idx{$id}{$idx} = 1;
}
}
close FILE;
open FILE, "file-2" or die "Couldn't open file-2";
open OUTFILE, ">file-3" or die "Couldn't open file-3";
my (undef, @ref) = split /\s+/, <FILE>;
while(<FILE>) {
my ($id, @src) = split /\s+/;
my $line = "$id";
for (my $i = 0; $i <= $#src; $i++) {
my $e = $keep_idx{$id}{$i} ? $src[$i] : $ref[$i];
$line .= " $e";
}
print OUTFILE "$line\n";
}
close OUTFILE;
close FILE;