Perl数组问题

Perl数组问题,perl,arrays,Perl,Arrays,从来没有做过太多的编程——在工作中被指控操纵来自评论卡的数据。到目前为止,我已经使用perl使数据库能够正确地将其每日注释放入数组中。注释是数据库中的每一行文本,所以我只是在换行符上拆分数组 my @comments = split("\n", $c_data); 是的,这是我第一次编程,花了我太长时间才弄明白 现在,我需要根据大写的单词将这些数组元素(我应该这样称呼它们吗?)组织到它们自己的独立标量中(这是数据库的一种行为,它曾一度损坏) 数组的两个元素的外观示例: print "$comm

从来没有做过太多的编程——在工作中被指控操纵来自评论卡的数据。到目前为止,我已经使用perl使数据库能够正确地将其每日注释放入数组中。注释是数据库中的每一行文本,所以我只是在换行符上拆分数组

my @comments = split("\n", $c_data);
是的,这是我第一次编程,花了我太长时间才弄明白


现在,我需要根据大写的单词将这些数组元素(我应该这样称呼它们吗?)组织到它们自己的独立标量中(这是数据库的一种行为,它曾一度损坏)

数组的两个元素的外观示例:

print "$comments[0]\n";
This dining experience was GOOD blah blah blah.

这些“好”或“坏”或“最好”已经由数据来源的数据库大写


在Perl中,根据这些大写单词从数组中将这些行转换成标量的最简单方法是什么?

您可以使用正则表达式,例如:

if ($comments[$i] =~ /GOOD/) {
    # good comment
}
或者更一般地说

if ($comments[$i] =~ /\b([A-Z]{2,})\b/) {
    print "Comment: $1\n";
}

这里,\b表示单词边界,()用于提取捕获的文本,[A-Z]表示一组大写字符-大写字母,{2,}表示必须有前一个类定义的2个或更多字符。

如果我理解正确,您希望合并与某个单词匹配的数组元素。您可以这样做:

my @bad_comments = grep { /\bBAD\b/ } @comments;
my @good_comments = grep { /\bGOOD\b/ } @comments;
这样,所有的“好”和“坏”注释都会进入各自的数组

现在,如果您需要将它们合并到一个标量中,您需要
加入它们(与
拆分相反):

当您希望按任意字符串键对数据进行分组时,请思考。在这种情况下,您有一系列好的评论和一系列坏的评论。如果你有一系列所谓的评论呢?基于数组变量
@good
@bad
@soso
的策略很快就会崩溃

在完全理解以下代码之前,您还有一些方法要做:

#!/usr/bin/perl

use strict; use warnings;

use Regex::PreSuf;

my %comments;

my @types = qw( GOOD BAD ); # DRY
my $types_re = presuf @types;

while ( my $comment = <DATA> ) {
    chomp $comment;
    last unless $comment =~ /\S/;

    # capturing match in list context returns captured strings
    my ($type) = ( $comment =~ /($types_re)/ );
    push @{ $comments{$type} }, $comment;
}

for my $type ( @types ) {
    print "$type comments:\n";

    for my $comment ( @{ $comments{$type} } ) {
        print $comment, "\n";
    }
}

__DATA__
This dining experience was GOOD blah blah blah.
Overall this was a BAD time and me and my blah blah.
#/usr/bin/perl
严格使用;使用警告;
使用Regex::presf;
我的%评论;
我的@types=qw(好的坏的)#干的
my$types\u re=presf@types;
while(我的$comment=){
chomp$comment;
最后,除非$comment=~/\S/;
#在列表上下文中捕获匹配将返回捕获的字符串
我的($type)=($comment=~/($types\u re)/);
推送{$comments{$type}},$comment;
}
对于我的$type(@types){
打印“$type注释:\n”;
对于我的$comment(@{$comments{$type}}){
打印$comment,“\n”;
}
}
__资料__
这顿饭真是太棒了。
总的来说,这是一个糟糕的时刻,我和我的诸如此类。

在我看来,最好是创建一个基于磁盘的某种数据库(?),将注释和类型存储为单独的数据

然后使用其他发布的解决方案之一将现有数据导入其中


这里唯一的问题是,要将SQLite与Perl结合使用,您需要学习Perl的DBI层和一些SQL。

我会将所有注释存储到数组散列数据结构中,关键是大写的单词。 这里有一个通用的解决方案,可以抓住任何大写的单词(假设每个评论只有一个),而不仅仅是好的和坏的:

use strict;
use warnings;

my @comments = <DATA>;
chomp @comments;

my %data;
for (@comments) {
    my $cap;    
    for (split) {
        $cap = $_ if /^[A-Z]+$/;
    }
    if ($cap) { push @{ $data{$cap} }, $_ }
}
use Data::Dumper; print Dumper(\%data);

__DATA__
This is GOOD stuff
Here's some BAD stuff.
More of the GOOD junk.
Nothing here.
不知道你所说的“组织”和“基于”是什么意思

如果您的意思是生成任何大写单词的列表,每个单词都有一个包含该单词的行列表(类似于toolic的解决方案,您可以这样做:

my %CAPS = ();

map {
    my ($word) = /(\b[A-Z]+\b)/;
    push( @{ $CAPS{$word} }, $_)
} @comments;
这将建立单词到事物的映射,在本例中,事物将是行列表


您可以将这些列表称为$CAPS{'GOOD'}或$CAPS{'BAD'},或$CAPS{whatever}。

一个您期望的输出示例会有所帮助。此外,如果注释包含多个关键字(例如,“GOOD”和“BAD”)“它们各自的标量”会发生什么情况---你是什么意思?你想要一个字符串包含所有好的行,另一个字符串包含所有坏的行,第三个字符串包含所有最好的行?或者别的什么?(“数组元素”很好,顺便说一句。)这就是我在Python中要做的(我不知道Perl)def rate(st):return int(st.find('GOOD')>-1)-int(st.find('BAD')>-1)它返回-1、0或1,这取决于该字符串中是否有好、坏、两者都有或两者都没有。但是,您可能需要添加断言,即每个字符串最多有一个评级。如果有2+,则抛出一个错误。@Dave Hinton--是的,这正是我的意思。@Michael Carman--这是一个很好的问题。Tim,祝贺您取得了这一成绩。如果你还没有拿到一本书,那就买一本“学习Perl”这本书吧。我只是不推荐它。另外,SO和Perlmonks.org都是很好的资源,可以帮助你发展新技能。
use strict;
use warnings;

my @comments = <DATA>;
chomp @comments;

my %data;
for (@comments) {
    my $cap;    
    for (split) {
        $cap = $_ if /^[A-Z]+$/;
    }
    if ($cap) { push @{ $data{$cap} }, $_ }
}
use Data::Dumper; print Dumper(\%data);

__DATA__
This is GOOD stuff
Here's some BAD stuff.
More of the GOOD junk.
Nothing here.
$VAR1 = {
          'BAD' => [
                     'Here\'s some BAD stuff.'
                   ],
          'GOOD' => [
                      'This is GOOD stuff',
                      'More of the GOOD junk.'
                    ]
        };
my %CAPS = ();

map {
    my ($word) = /(\b[A-Z]+\b)/;
    push( @{ $CAPS{$word} }, $_)
} @comments;