【问题标题】:Print each hash key and its values in new file?在新文件中打印每个哈希键及其值?
【发布时间】:2013-04-30 09:08:55
【问题描述】:

我制作了一个散列散列,其中文件的所有行都根据它们的第 5 个字段的值排序到“主”散列的一个键中。

%Tiles 有 n 个键,其中每个键是不同的 $Tile_Number

%Tiles 的每个元素的值是对哈希哈希的引用,该哈希哈希包含所有以$Tile_Number 为当前哈希键编号的行。这些新键(行)中的每一个的值都只有 1。

$Tiles{$Tile_Number}{$Line}=1 ,其中$Tiles{$Tile_Number} 有许多$Line=1 条目。

我想在单独的文件中打印每个 $Tiles{$Tile_Number} 哈希,最好在创建 $Tile_Number 键时创建文件,并在添加每个新的 $Tiles{$Tile_Number}{$Line}=1 时打印,以节省内存。

最好不要打印最终值 (1),但我想我可以取消它。

如何告诉 Perl 为“主”散列中的每个键打开一个新文件并打印其所有键?

代码:

use strict;
use warnings;


my ($Line) = "";
my (@Alignment_Line) = ();
my (%Tiles) = ();

my $Huge_BAM_File= $ARGV[0] or die $USAGE;

open(HUGE_BAM_FILE,"< $Huge_BAM_File") || die "Sorry I couldn't open the INPUT file:   $Huge_BAM_File !\n";

while(<HUGE_BAM_FILE>){

    ### Remove new line characters "\n"
    ### Split each line by "\t" and by ":" (for fields within READ ID FIELD)
    chomp;
    $Line = $_;
    @Alignment_Line = split(/\t+|\:/, $Line);

    my $Tile_Number = $Alignment_Line[4]


    ##########################################################
    ### Fill in hash of hashes %Tiles                      ###
    ### Key = $Tile_Number                                 ###
    ### Second key is $Line                    ###
    ### and is filled with a 1                     ###  
    ### Each key contains all the alignments with that tile### 
    ### number                                     ###
    ##########################################################

     $Tiles{$Tile_Number}{$Line} = 1;
     ##Here, I would like to write this new entry into the corresponding file, 
     and maybe remove it from the hash so the program doesn't run out of memory.
}

关闭(HUGE_BAM_FILE); 关闭(ALL_OUTPUTS_GENERATED);

【问题讨论】:

  • 您期望$Tile_Number 有多少个值,对于每个值,$Line 有多少个值?我认为您寻求的答案取决于这些数字。另外,考虑到许多现代计算机中的可用 RAM,您为什么要节省内存?
  • 我期待 96 个 $Tile_Number,每个包含 10-1500 万个条目,并为 8 个项目并行执行此操作。

标签: perl hash printing file-handling


【解决方案1】:

我认为你应该有一个数组的散列,而不是一个散列的散列。但是,听起来您可以使用此方法打印出哈希值

while (my ($tile, $lines) = each %Tiles) {
    open my $fh, '>', "$tile.txt" or die $!;
    print $fh $_ for keys %$lines;
}

请注意,这些行的读取顺序不会相同。你必须为此使用一个数组。

我不清楚您在添加每一行并节省内存时打印的想法。您的意思是要打印每一行而不是将其添加到哈希中?也许您应该向我们展示您的完整代码。


更新

这是您可能喜欢的替代方案。它根本不存储文件中的数据。相反,它在读取时从每一行中提取图块编号,然后写入与该编号对应的文件。

有一个文件句柄的散列,其中瓦片编号作为键,每次读取一行时,都会检查散列以查看是否已经存在该瓦片编号的文件句柄。如果没有,则在写入该行之前打开一个新的。

use strict;
use warnings;

my $USAGE;

my $bam_file = $ARGV[0] or die $USAGE;

open my $bam, '<', $bam_file"
    or die qq{Unable to open "$bam_file" for input: $!};

my %filehandles;

while (<$bam>) {
    chomp ($line = $_);
    my @fields = split /[\t:]/, $line;
    my $tile = $fields[4];
    unless ($filehandles{$tile}) {
      my $file = "$tile.txt";
      open $filehandles{$tile}, '>', $file
          or die qq{Unable to open "$file" for output: $!};
    }
    print $filehandles{$tile} $_;
}

while (my ($tile, $fh) = each %filehandles) {
  close $fh
      or warn qq{Unable to close file for tile number $tile: $!};
}

【讨论】:

  • 谢谢,鲍罗丁!我不需要以与阅读时相同的方式对这些行进行排序。我曾想过为每个 $Tile_Number 使用一个数组,但后来我不知道如何打印数组中的每个 $i :( 我将把我的代码粘贴到我的问题中。
  • @CarmenSandoval:我在我的答案中添加了一个您可能感兴趣的替代设计。
  • 哇,鲍罗丁,这好多了。非常感谢,希望这对将来需要做类似事情的其他人有用:)我对您的代码只有一个问题-这部分是如何工作的:? while (my ($tile, $fh) = each %filehandles) { close $fh
  • 另一个菜鸟问题 - 是否可以通过管道将 $ARGV[0] 传递给脚本?即 perl 脚本的输入来自对 .bam 文件的先前操作,将其解压缩为 .sam 文件。最好先编写 .sam 文件,然后像往常一样将其传递给 perl 脚本,但我只是想知道......谢谢!!!
猜你喜欢
  • 1970-01-01
  • 2014-08-09
  • 1970-01-01
  • 1970-01-01
  • 2021-02-18
  • 1970-01-01
  • 2011-10-27
  • 1970-01-01
  • 2012-08-10
相关资源
最近更新 更多