2012-11-28 53 views
3

我有散列以下散列:填入散列perl的

my %MacroA = ('Category' => {}, 'Item' => {}, 'Description' => {}, 'Score' => {}); 

我想通过一个文件是循环,然后将新元素添加到不同的哈希值。比方说,该行包含“布局”我想将其存储在“类别”每次看到它的时候

我所做的是:

while (my $line = <$file>) {           

if ($line =~ /\b(layout)\b,/) { 
foreach my $categories (keys $MacroA{'Category'}) { 
    $MacroA{Category} = $1; 
} 
} 
+0

满足包含'layout'的行后,%MacroA的期望值是多少? – choroba

+0

%MacroA ='Category'=>'layout'@choroba –

+2

您的问题包含的示例代码与http://stackoverflow.com/questions/13566521/hash-of-hashes-perl中的代码非常相似。我不知道你是否是TheBlackCorsair的用户,或者你恰好在同一个班级,但该帖子中的问题和答案可以帮助你。 – MattLBeck

回答

1

下面是一个完整的程序分割成不同的块。要运行它,将答案复制并粘贴到名为populate的文件中,但删除评论部分,如本段落。

几乎所有的Perl程序(尤其是当你还是个新手)应先从

#! /usr/bin/env perl 

use strict; 
use warnings; 

第一行告诉系统如何执行你的程序。启用strictwarnings实用程序将帮助您避免常见错误,并帮助解释您的程序在出现令人惊讶的行为的情况下正在执行的操作。

根据你的问题,你想要的数据结构是散列数组。每个所述阵列的“行”或元件将对应于所述输入文件中的一行,并且将具有形式

# { Category => '...', Item => '...', Description => '...', Score => '...' } 

方案还将从输入读出的列名。

该代码使用Perl的“钻石算子”来读取每一行输入。 chomp删除尾随的换行符(如果存在)。

如果行告诉我们的头名(,它#开始),我们每个字段存储在@columnsucfirst位可能不熟悉:它u pper c ases 第一个字符串的字符。由于有多个列名,因此我们使用mapucfirst应用于每个列名。

否则,该行代表一个数据行。我们将split的行填入由逗号分隔的字段中,并将它们加载到新的散列中。 push行在@MacroA的末尾添加了一个引用(在散列之前使用反斜杠创建)。

my @MacroA; 
my @columns; 
while (<>) { 
    chomp; 

    if (s/^#//) {        #/fix Stack Overflow coloring 
    @columns = map ucfirst, split /\s*,\s*/; #/ditto 
    } 
    else { 
    my %row; 
    @row{@columns} = split /,/; 
    push @MacroA, \%row; 
    } 
} 

请注意,上面的拆分是na&iumlaut; ve。要处理常规CSV输入,请使用CSV modules on CPAN之一。

Data::Dumper模块可用于快速打印复杂数据结构的内容。把它放在你的调试工具包里。

use Data::Dumper; 
$Data::Dumper::Indent = $Data::Dumper::Terse = 1; 
print Dumper \@MacroA; 

__END__ 

下面给出

#category, item, description, score 
layout,f.4,Macro placement clearance,pass 
layout,f.14,No area congestion,pass 
layout,f.17,placement collar diode,fail 
layout,f.18,placement collar buffer,pass 
layout,f.26,tie connection,fail 
layout,f.28,CTS allowed cell,fail 
layout,f.29,CTS allowed layed,pass 
layout,f.31,Clock De-cap cell,fail 
layout,f.33,Clock non default rule,fail

文件input与内容的样品运行如下。

$ perl populate input 
[ 
    { 
    'Score' => 'pass', 
    'Item' => 'f.4', 
    'Description' => 'Macro placement clearance', 
    'Category' => 'layout' 
    }, 
    { 
    'Score' => 'pass', 
    'Item' => 'f.14', 
    'Description' => 'No area congestion', 
    'Category' => 'layout' 
    }, 
    { 
    'Score' => 'fail', 
    'Item' => 'f.17', 
    'Description' => 'placement collar diode', 
    'Category' => 'layout' 
    }, 
    { 
    'Score' => 'pass', 
    'Item' => 'f.18', 
    'Description' => 'placement collar buffer', 
    'Category' => 'layout' 
    }, 
    { 
    'Score' => 'fail', 
    'Item' => 'f.26', 
    'Description' => 'tie connection', 
    'Category' => 'layout' 
    }, 
    { 
    'Score' => 'fail', 
    'Item' => 'f.28', 
    'Description' => 'CTS allowed cell', 
    'Category' => 'layout' 
    }, 
    { 
    'Score' => 'pass', 
    'Item' => 'f.29', 
    'Description' => 'CTS allowed layed', 
    'Category' => 'layout' 
    }, 
    { 
    'Score' => 'fail', 
    'Item' => 'f.31', 
    'Description' => 'Clock De-cap cell', 
    'Category' => 'layout' 
    }, 
    { 
    'Score' => 'fail', 
    'Item' => 'f.33', 
    'Description' => 'Clock non default rule', 
    'Category' => 'layout' 
    } 
]
1

我认为你需要一个数组哈希表来代替:

my %MacroA = ('Category' => [], 'Item' => [], 'Description' => [], 'Score' => []); 

while (my $line = <$file>) {           

if ($line =~ /\b(layout)\b,/) { 
foreach my $categories (keys $MacroA{'Category'}) { 
    push $MacroA{Category}, $1; 
} 
} 
3

你的问题很混乱 - 问,但你的问题似乎是因为你在参考而不是散列上做keys。较新的perls确实支持这一点,但你可能会使用旧版本。

在你的例子中$MacroA{'Category'}返回一个散列引用,而不是散列。您使用'Category' => {}初始化散列,并且{}是对空匿名散列的引用。

要将散列引用转换为散列,可以使用%{ ... }表示法;在这种情况下,你会写keys %{ $MacroA{'Category'} }。是的,这很丑陋,这就是为什么Perl更改为支持keys的参考。

但请注意,您的下一行是$MacroA{Category} = $1;,它将替换$1中的任何内容,可能是字符串"layout"。这不是一个参考,所以下一次while循环时,你的脚本将会碰撞。你可能想要做一个多级散列,像$MacroA{Category}{$1} = $file或类似的东西,这取决于你想在散列中建立什么样的数据,但是你不太清楚你想要实现什么。另一个建议散列散列的答案可能是你所期望的。在这种情况下,如果使用较旧的perl,则符号@{ ... }会将数组引用转换为您可以与push一起使用的数组。

+0

@彼得·科利特什么即时试图实现的是,我有followingfile: –

+0

'#category,项目描述,得分 布局,中四,宏观布局间隙,通过 布局,F .14,无区域拥堵,通过 布局,f.17,放置环二极管,失败 布局,f.18,放置领缓冲区,通过 布局,f.26,连接连接,失败 布局,f.28, CTS允许单元格,失败 布局,f.29,CTS允许放置,通过 布局,f.31,时钟删除单元格,失败 布局,f.33,时钟非默认规则,失败,我想存储从每行到“描述”的“布局” –

1

你的问题很混乱。只需添加“布局”,将种类关键是操作简单,无循环涉及:

while (my $line = <$file>) {           
    if ($line =~ /\blayout\b,/) { 
     $MacroA{Category} = 'layout'; 
    } 
} 
2

它看起来就像你正在试图做一种名为列的东西,在这里。这是 非常简单,如果你知道如何去做。

从彼得您的评论去(“[我]要存储‘布局’推算的各 行‘说明’”),这就是这个代码可以让你做:它。

因为我看到一个散列的主要情况是记录本身,这是唯一的散列 这个演示使用。它将它们存储在一个数组中。我真的不知道你如何 想要从你的例子中索引它们。你似乎对你如何处理它们感到有点困惑。当然,处理其中的每一行都不是很有用,然后将其存储为“类别”字段。

use strict; 
use warnings; 

my @columns = qw<field1 field2 field3 field4>; 
my @list; 
my $fh = \*::DATA; 
my $header = <$fh>; 
if (substr($header, 0, 1) eq '#') { 
    ($header) = $header =~ m/#(.*)/; 
    $header =~ s/\s+$//; 
    @columns = split /,\s*/, $header; 
} 
else { 
    seek($fh, 0, 0); # go back 
} 

# optional statement to capitalize field names 
@columns = map { ucfirst } @columns; 

while (my $line = <$fh>) { 
    next unless $line =~ m/^\s*layout\b/; 
    $line =~ s/\s*$//; 
    # store fields by hash slice in the tip of the array 
    @{ $list[@list] }{ @columns } = split /,\s*/, $line; 
} 

__DATA__ 
#category, item, description, score 
layout,f.4,Macro placement clearance,pass 
layout,f.14,No area congestion,pass 
layout,f.17,placement collar diode,fail 
layout,f.18,placement collar buffer,pass 
layout,f.26,tie connection,fail 
layout,f.28,CTS allowed cell,fail 
layout,f.29,CTS allowed layed,pass 
layout,f.31,Clock De-cap cell,fail 
layout,f.33,Clock non default rule,fail 

虽然它不是万能的,你可能希望它是,复制记录到 一个数组“处理它”的简单模型,我们可以做这样的事情 代替:

my %by_item; 
while (my $line = <$fh>) { 
    next unless $line =~ m/^\s*layout\b/; 
    $line =~ s/\s*$//; 
    my %h; 
    @h{ @columns } = split /,\s*/, $line; 
    $by_item{ $h{Item} } = \%h; 
    ### OR 
    # push @{ $by_item{ $h{Item} } }, %h; 
} 

你也可以这样做:

my %by_field; 
... 
$by_field{Item}{ $h{Item} }    
    = $by_field{Description}{ $h{Description} } 
    = \%h 
    ;