【问题标题】:Split an array into chunks [closed]将数组拆分为块[关闭]
【发布时间】:2014-12-22 02:47:46
【问题描述】:

我的目标:制作包含 5 个测验问题的文件,并将文件分解为这 5 个问题。我的代码对我来说很有意义(我如何在 cmets 中看到它),但是 perl 告诉我我在“@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";
}

【问题讨论】:

  • 你能发布你的问题文件吗?听起来可能有一种更简单的方法来做你想做的事情。

标签: arrays perl splice


【解决方案1】:

如果不查看输入文件的格式,就很难建议您如何将其分成五个块,但这里有一些您可以使用的通用指针。

读取文件,一次一行

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

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'
  ]
];

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

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

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

【讨论】:

    【解决方案2】:

    我认为你可以从中学到的最大和最好的教训是,你添加的任何 cmets不要让你的代码按照他们所说的去做。只是希望和愿望的评论,比根本没有cmet还要糟糕。

    您应该仅在您的代码非常复杂以至于不清楚您所写的内容时才对其进行注释。在这种情况下,您似乎正在读取输入文件并打印相同的内容。这不需要评论,尤其是一厢情愿的想法。

    • 总是use strict 和use warnings 在每个 Perl 程序的顶部

    • 然后这个。没关系,但是您正在清空两个空数组并且有一个奇怪的评论。为什么是“尝试”?

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

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

      &lt;$test&gt; 是 true 值时,您正在循环。从文件句柄读取从不关闭文件

    • 这个应该没问题

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

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

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

    • 现在有这个

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

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

    • 然后

      print @question1, "\n";
      

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

    之后是 while 循环的结束,所以您只需再次执行相同的操作,一次一行。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-09
      • 2022-01-06
      • 2012-06-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多