2017-04-13 55 views
1

我解析的文本文件看起来像这样:如何将文本文件分成两个数组?

ABCD 
EFGH 
IJKL 

MNOP 
QRST 
UVWX 

是否有可能在它的两个4x3的阵列的方式来解析这个在Perl?例如,array1[2][2] = Kand array2[0][1] = N。 代码:

#!/usr/bin/perl 
use strict; 
use warnings; 
use diagnostics; 

open(FH, '<', 'gwas.txt') or die "Couldn't open file $!"; 

while(<FH>) { 

    #parse file into 2 arrays 
} 
close(FH); 
+1

这是一个谜题?什么样的计数系统具有带'(2,4)'索引的'K'和带有'(1,0)'的'N'?你可以解释吗?但首先 - 你能告诉我们你做了什么以及你有什么问题吗?预计这里的问题是关于你的code_。 – zdim

+0

@zdim我的错!只是修复这些并添加了代码。 –

+0

这样比较好,谢谢(仍然,我认为你的意思是'a [2] [2] == K' ...?)至于代码:通过让数据结构在每个数据结构中携带_references_来创建多维结构插槽。阅读参考资料:tutorial [perlreftut](http://perldoc.perl.org/perlreftut.html)和一本食谱[perldsc](http://perldoc.perl.org/perldsc.html)。你想要array array,在'pelrdsc' – zdim

回答

1

的过程中的评论所解释的,冷凝的

my @matrix = map { [ split '', $_ ] } <$fh>; 

金刚石操作者<>list context返回的所有行(见I/O operators),从而每个由块中处理的map和返回的列表分配给@matrix

split打破每行($_)成字符('')的块和anonymous array由该列表([...])的。给定split的默认值可以写为map { [ split '' ] }

始终使用词法文件句柄,最好这样

my $file = 'gwas.txt'; 
open my $fh, '<', $file or die "Couldn't open $file: $!"; 

正如在评论中指出,该处理整个文件分割成一个阵列。为了处理两个文本块,每个文本块放到它自己的数组中,我们可以把它写成一个循环(并用空行来区分块)。

my @matrix; 
my $index = 0;  
while (<$fh>) { 
    $matrix[$index++] = [ split '', $_ ]; 
} 

这使得一个匿名数组[ ... ]与线元件和它的阵列中@matrix分配给$index点(并且递增索引)。这样做的另一种方法是

my @row = split '', $_; 
$matrix[$index++] = \@row; 

其中一个新的数组在每次迭代中被构造并且被赋值给它的引用。

然后我们需要用空行来区分块。我们还需要管理这两个数组,通过在另一个数据结构中引用数组(矩阵)很好地完成了什么,比如说一个数组。

use warnings; 
use strict; 
use Data::Dump qw(dd); 

my $matrices; # will be an arrayref, for references to matrices 

my $file = 'matrices.txt'; 
open my $fh, '<', $file or die "Can't open $file: $!"; 

my @matrix; 
my $index = 0; 
while (<$fh>) { 
    chomp; 

    if (/^\s*$/) {      # blank line, done with one matrix 
     $index = 0;     # reset index 
     push @$matrices, [ @matrix ]; # store anonymous array for @matrix 
    } 
    else { 
     @matrix[$index] = [ split '', $_ ]; 
     ++$index; 
    } 
} 
push @$matrices, [ @matrix ];   # the last one in the file 

close $fh; 

print "Spot check: \$matrices->[0][2][2]: $matrices->[0][2][2]\n"; 
dd($matrices); 

这对数据持有假设,通常它具有确切的预期格式。

请参阅参考资料perlreftut的教程和关于数据结构perldsc的食谱。

另请参阅answer by xxfelixxx,所有这些都以非常不同的方式进行。

还有很多其他的方法可以做到这一点。

+0

好的真棒,这是有道理的。但我的意图是有两个单独的阵列,目前只有一个。 –

+0

好的,非常感谢你让我开始!非常感谢 –

+0

@KyleWeise哦,我现在看到你的意思是两个数组。你是对的 - 这会将两个文本块存入一个空白行中。这是作为一个基本的示范。正如在该评论中概述的那样,为了您的整个问题,将它写成一个循环。当你打空行时,从第二个数组开始。 – zdim

0
#!/usr/bin/env perl 
use strict; 
use warnings; 

my $arrays = []; 
my $count = 0; 
my $row = 0; 

# Read data and store in $arrays 
while(<DATA>) { 
    if (my ($letters) = m/^(\w+)\s*$/) { 
     # Store letters 
     $arrays->[$count]->[$row] = [ split //, $letters ]; 
     $row++; 
    } else { 
     # Next batch 
     $count++; 
     $row = 0; 
    } 
} 

# Print it out with indices 
for my $iarray (0 .. $count) { 
    print "------ Matrix $iarray ------\n"; 
    my @rows = @{ $arrays->[$iarray] }; 
    for my $irow (0 .. $#rows) { 
     my @cols = @{ $rows[$irow] }; 
     for my $icol (0 .. $#cols) { 
      print "($irow,$icol) -> " . $cols[$icol] . "\n"; 
     } 
    } 
} 

__DATA__ 
ABCD 
EFGH 
IJKL 

MNOP 
QRST 
UVWX 

输出

------ Matrix 0 ------ 
(0,0) -> A 
(0,1) -> B 
(0,2) -> C 
(0,3) -> D 
(1,0) -> E 
(1,1) -> F 
(1,2) -> G 
(1,3) -> H 
(2,0) -> I 
(2,1) -> J 
(2,2) -> K 
(2,3) -> L 
------ Matrix 1 ------ 
(0,0) -> M 
(0,1) -> N 
(0,2) -> O 
(0,3) -> P 
(1,0) -> Q 
(1,1) -> R 
(1,2) -> S 
(1,3) -> T 
(2,0) -> U 
(2,1) -> V 
(2,2) -> W 
(2,3) -> X 
1
  1. 分割数据成段的阵列。
  2. 将每一段拆分为一行数组。
  3. 将每一行分割成一个字符数组。

这可以通过使用可以实现以下两种:

my @arrays; 
{ 
    local $/ = ""; # Paragraph mode 
    @arrays = map { [ map { [ split // ] } split /\n/ ] } <>; 
} 

my @arrays; 
{ 
    local $/ = ""; # Paragraph mode 
    push @arrays, [ map { [ split // ] } split /\n/ ] while <>; 
} 

他们生产:

$VAR1 = [ 
      [ 
      [ 'A', 'B', 'C', 'D' ], 
      [ 'E', 'F', 'G', 'H' ], 
      [ 'I', 'J', 'K', 'L' ] 
      ], 
      [ 
      [ 'M', 'N', 'O', 'P' ], 
      [ 'Q', 'R', 'S', 'T' ], 
      [ 'U', 'V', 'W', 'X' ] 
      ] 
     ]; 

所以,

say $arrays[0][2][2]; # K 
say $arrays[1][0][1]; # N 
+0

谢谢!这看起来很直接。你能解释一下开启/关闭大括号的原因吗?它们是否与'@ arrays'声明关联,还是有其他含义? –

+0

它们是['map'](http://perldoc.perl.org/functions/map.html)'map BLOCK LIST'语法的一部分。 – ikegami

+0

你几乎可以包括你如何打印输出?由于格式,我假设'Data :: Dumper'。 –