将数组拆分为块

时间:2014-10-26 22:44:54

标签: arrays perl splice

我的目标:收集5个测验问题的文件,并将文件分解为5个问题。我的代码对我有意义(我在评论中看到了它),但perl告诉我,我在第34行使用了一个未初始化的变量; @ question1 = join ...."任何人都可以对此有所了解吗?我以为我之前正在初始化这些值。提前谢谢。

my $filename = "test.txt";                    #open file
open my $test, '<', $filename
    or die "Couldn't open file '$filename' $!\n";

my @lines = ();                     #attempt to initialize variables
my @question1 = ();

while (<$test>) {   #while file is open

    push (@lines, $_);      #push each line into the array "lines"
    my @lines = split /\n/, @lines;  #split the array at the newlines

    @question1 = join ("\n", sort (@lines[0..5]));  
    #make @question1 = to lines 0-5 of the array

        print @question1, "\n";
}

2 个答案:

答案 0 :(得分:2)

如果没有看到输入文件的格式,就建议你如何将其分成五个块更加困难,但这里有一些你可以使用的一般指针。

一次读取一行文件

如果您的输入文件每行有一个问题,您可以使用与您在脚本中发布的方法类似的方法来阅读它。

test.txt的内容:

Q1. Why colour is red?
Q2. How many is too many?
Q3. What about me?

脚本:

use strict;
use warnings;
use Data::Dumper; # to visualise data structures

my $filename = "test.txt";
open my $test, '<', $filename
    or die "Couldn't open file '$filename' $!\n";

my @lines;
# go through text.txt one line at a time
while (<$test>) {
    chomp;                # remove the line ending
    push @lines, $_;      # push each line into the array "lines"
}
# view the data structure    
print Dumper \@lines;

输出:

$VAR1 = [
  'Q1. Why colour is red?',
  'Q2. How many is too many?',
  'Q3. What about me?'
];

这样做的简便方法是:

open my $test, '<', $filename
    or die "Couldn't open file '$filename' $!\n";

my @lines = <$test>;      # read all lines into @lines
chomp @lines;             # remove all the line endings

print Dumper \@lines;

输出:

$VAR1 = [
  'Q1. Why colour is red?',
  'Q2. How many is too many?',
  'Q3. What about me?'
];

现在你已经在数组@lines中得到了所有问题;问题1为$lines[0],问题2为$lines[1],问题3为$lines[2],依此类推。

以块的形式读取文件

如果您的输入文件有一个问题后跟三个可能的答案(如上一个问题),那该怎么办?输入文件格式示例:

1.) question one text
 a.) solution a
 b.) solution b
 c.) solution c

2.) question two text
 a.) solution 2a
 b.) solution 2b
 c.) solution 2c

3.) question three text
 a.) solution 3a
 b.) solution 3b
 c.) solution 3c

您可以将input record separator, $/设置为自定义值,将文件拆分为您认为的记录。默认情况下,$/会将一行视为记录。如果您将$/设置为"",它将以段落模式读取文件,这意味着任意两个或更多连续新行的集合(即\n\n\n\n\n,等)将划定记录。要解析上述格式的文件,您可以:

my $filename = "test.txt";
my @lines;
{
    local $/ = "";
    open my $test, '<', $filename
        or die "Couldn't open file '$filename' $!\n";
    @lines = <$test>;
}
print Dumper \@lines;

输出:

$VAR1 = [
  '1.) question one text
 a.) solution a
 b.) solution b
 c.) solution c

',
  '2.) question two text
 a.) solution 2a
 b.) solution 2b
 c.) solution 2c

',
  '3.) question three text
 a.) solution 3a
 b.) solution 3b
 c.) solution 3c
'
];

如果我们想对输入执行任何操作,则为输入记录分隔符提供不同的值非常有用。例如,让我们用一组行分开每个问题:

my $filename = "test.txt";
my @lines;
my @questions;
{
    local $/ = "";
    open my $test, '<', $filename
        or die "Couldn't open file '$filename' $!\n";
    while (<$>) {
        # split up the input into lines
        my @temp = split "\n", $_;

        # find lines starting with a digit and a full stop ( /^\d\./ ) from @temp
        # push them on to the array @questions
        push @questions, grep /^\d+\./, @temp;

        # push a reference to @temp on to @lines (@lines is now an array of arrays)
        push @lines, [ @temp ];
    }
}
print Dumper \@questions;

输出:

$VAR1 = [
  '1.) question one text',
  '2.) question two text',
  '3.) question three text'
];

查看@lines的结构:

print Dumper \@lines;

输出:

$VAR1 = [
  [
    '1.) question one text',
    ' a.) solution a',
    ' b.) solution b',
    ' c.) solution c'
  ],
  [
    '2.) question two text',
    ' a.) solution 2a',
    ' b.) solution 2b',
    ' c.) solution 2c'
  ],
  [
    '3.) question three text',
    ' a.) solution 3a',
    ' b.) solution 3b',
    ' c.) solution 3c'
  ]
];

以单个字符串形式读取文件

处理文件内容的另一种常用方法是将文件作为一个长字符串读取。为此,您需要将输入记录分隔符设置为undefined:

test.txt的内容:

Q1. Why colour is red?
Q2. How many is too many?
Q3. What about me?

脚本:

my $filename = "test.txt";
my $lines;
{
    local $/;
    open my $test, '<', $filename
        or die "Couldn't open file '$filename' $!\n";
    $lines = <$test>;
}
print Dumper($lines);

输出:

$VAR1 = 'Q1. Why colour is red?
Q2. How many is too many?
Q3. What about me?
';

您应该能够在这些方法中找到至少一种适合您输入和目的的方法。如果您不能,则需要发布您的输入文件以及您希望输出的内容。

More information on file operations in perlfaq5

More information on Perl's special variables in perlvar

答案 1 :(得分:1)

我认为您可以从中学到的最重要和最好的教训是,您添加的任何评论不要使您的代码按照他们的意思行事。只是希望和愿望的评论远比没有评论更糟糕。

如果代码非常复杂,以至于不清楚你写的是什么,那么你应该只评论你的代码。在这种情况下,您似乎正在读取输入文件并打印相同的内容。这并不需要评论,特别是在一厢情愿的情况下。

  • 总是 use strictuse warnings位于每个 Perl程序的顶部

  • 然后这个。没关系,但是你要清空两个空数组,并有一个奇怪的评论。为什么这是&#34;尝试&#34;?

    my @lines = ();                     #attempt to initialize variables
    my @question1 = ();
    
  • 这是谎言

    while (<$test>) {   #while file is open
    

    您在<$test> true 值时循环播放。从文件句柄中读取永远不会关闭文件

  • 这可能没关系

    push (@lines, $_);      #push each line into the array "lines"
    
  • 除了现在这个

    my @lines = split /\n/, @lines;  #split the array at the newlines
    

    声明全新且独立的数组@lines,并传递 @lines的第一个和第二个元素作为第二个元素split的第三个参数。请记住,到目前为止, @lines中只有文件的单行,因此您要分割一行在最后的换行符

  • 现在有了

    @question1 = join ("\n", sort (@lines[0..5]));  
    

    所以你重新加入你刚刚拆分的单行并将其填充到单元素数组@question1中以包含该拆分和重新加入的字符串

  • 然后

    print @question1, "\n";
    

    打印该单元素数组后跟换行符。

之后是while循环的结束,所以你只需要再次做同样的事情,一次一行。

你几乎将输入复制到输出,一次一行,通过将每一行拆分成单个元素数组并将其复制到另一个单元素数组中,