【问题标题】:Print different value each time key is called每次调用键时打印不同的值
【发布时间】:2017-02-27 03:30:07
【问题描述】:

我需要一些关于 Perl 的帮助。

我在一个文件中有一个 ID 和相应值的列表。每个 ID 都充当哈希散列中的一个键,因此每个键都有多个值。我正在尝试打开第二个文件并在每次遇到密钥时分配一个不同的值。这是我目前所拥有的:

此代码获取输入文件并构建哈希值。 $prot 是键,$dir 是值。每个键都有多个值。

open (IN, "file_name");
while (<IN>)
{
 ($prot, $dir) = split;
 push (@{$dir{$prot}}, $dir );
} 

在代码的第二部分,我想读取文件的每一行并使用该行中的第一列作为键来分配不同的值。每个键将在第二个文件中出现多次,并且对于每个实例,我希望它打印不同的值。

open (FH, "results_file");
while (<FH>)
{
chomp;
@a=split;
$prot=$a[1];
foreach  (values %dir)
{print "$a[1]"."\t"."@{$dir{$prot}}"."\n";}
}

现在代码的编写方式是在遇到键时打印每个键的所有值。

非常感谢您提供的任何帮助!

编辑:

第一个输入文件类似于

BC_123456     dir_6789
BC_456789     dir_3456
BC_234689     dir_1298
BC_123456     dir_3987
BC_876432     dir_7642

【问题讨论】:

  • 您能提供输入文件的样本吗?如果您使用 Data::Dumper;打印转储器($dir);在您的第一个示例结束时,数据结构看起来像您期望的那样吗?
  • 我添加了第一个输入文件的示例。我把它放入数组的哈希中后,数据结构看起来和我预期的一样。
  • 我正在为你想如何“分配不同的价值”而苦苦挣扎。您说“第一列”,但您使用第二列(注意从 split 中对数组的索引是从零开始的)。您想为哈希数组分配不同的值吗?还是您只是想临时分配一个值以用于打印目的?

标签: perl hash


【解决方案1】:

每个 ID 都充当哈希散列中的一个键

你实际上有一个数组哈希。

假设您要为第一个实例打印第一个值,为第二个实例打印第二个值,依此类推,您可以将遇到的每个键的值移出:

open (FH, "results_file");
while (<FH>)
{
chomp;
@a=split;
$prot=$a[1];
    foreach  (values %dir) {
        my $val = shift @{$dir{$prot}};
        print "$a[1]\t$val\n";
    }
}

这将从 HoA 条目中删除一个值,假设您以后不需要使用该数组。

【讨论】:

  • 首先,感谢您用数组的散列与散列的散列来纠正我! :-) 其次,我尝试了你的答案,当我尝试打印它时,它一直告诉我 $val 未初始化。
  • @sapo42 如果 $val 未初始化返回,则 (1) 该哈希位置的数组已经为空,或者 (2) 您已将 undef 值推送到数组中(如果您的示例数据不太可能是正确的)。打印完第一个输入文件中的所有值后,您希望发生什么?
【解决方案2】:

我认为这可以让您的代码正常工作。有一些最佳实践需要注意:

  • 您应该始终在严格和警告下运行。
    • use strict;
    • use warnings;
  • 我推荐open() 的三个参数版本,带有错误检查(or die "message $!";)和一个词法变量来存储文件句柄。
    • 见:
    • perldoc -f open
    • perldoc perlopentut
  • 使用完文件后关闭它们。
  • 除非您有充分的理由使用其他变量,否则应使用 my 引入(声明)变量。

我还做了一些更改,虽然我推荐,但它们不是必需的。

  • 删除变量 @a,因为您实际上并不需要它。
  • 清理了您的print,因为它很难阅读。你也可以试试printf
  • 您有两个名为 dir 的文件(%dir$dir)在这种情况下我觉得很困惑,所以我将 %dir 重命名为 %dirs

代码:

use strict;
use warnings;

my %dirs;

# Part 1 - Input
my $filename_input = "file_name.txt";
open(my $IN,'<',$filename_input) or die "Unable to open [$filename_input] for reading - $!";
while(<$IN>) {
    my ($prot, $dir) = split;
    push @{$dirs{$prot}}, $dir;
}
close $IN;

# Part 2 - Output
my $filename_results = "results_file.txt";
open(my $RESULTS,'<',$filename_results) or die "Unable to open [$filename_results] for reading - $!";
while(<$RESULTS>) {
    chomp;
    my $prot = (split)[1];
    foreach (values %dirs) {
        print "$prot\t@{$dirs{$prot}}\n"; # Or try: printf "%s\t%s\n",$prot,"@{$dirs{$prot}}";
    }
}
close $RESULTS;

文件名.txt

BC_123456     dir_6789
BC_456789     dir_3456
BC_234689     dir_1298
BC_123456     dir_3987
BC_876432     dir_7642

results_file.txt

don'tcare BC_123456
don'tcare BC_234689

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-02-04
    • 1970-01-01
    • 1970-01-01
    • 2018-08-02
    • 1970-01-01
    • 2022-08-05
    • 2020-12-18
    相关资源
    最近更新 更多