table {
border-collapse: collapse;
width: 100%;
margin-bottom: 1rem;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
th {
background-color: #f2f2f2;
}
tr:nth-child(even) {
background-color: #f9f9f9;
}
pre {
background-color: #f8f8f8;
padding: 15px;
border-radius: 4px;
overflow-x: auto;
}
1、创建一个哈希,键为水果名称,值为它们的常见颜色,然后将每个键/值对作为单独的一行打印出来,格式类似于“香蕉是黄色的”。
以下代码是实现该功能的示例:
use strict;
use warnings;
use diagnostics;
my %color_for = (
bananas => 'yellow',
apples =>'red',
oranges => 'orange',
);
for my $fruit (keys %color_for) {
my $color = $color_for{$fruit};
print "$fruit are $color
";
}
2、从 @fahrenheit 数组创建 @celsius 数组。
要从
@fahrenheit
数组创建
@celsius
数组,需要将
@fahrenheit
数组中的每个华氏温度值转换为摄氏温度值。转换公式是先减去 32,然后乘以 5/9。可以使用以下代码实现:
my @fahrenheit = ( 0, 32, 65, 80, 212 );
my @celsius = map { ( $_ - 32 ) * 5 / 9 } @fahrenheit;
3、将数字 1 到 10 逐行打印。
在 Perl 中可以使用以下代码实现:
for (my $i = 1; $i <= 10; $i++) {
print $i, "
";
}
4、计算并打印@numbers数组中数字的平均值。
可以使用以下代码实现:
sub average {
my @numbers = @_;
my $total = 0;
$total += $_ foreach @numbers;
return $total / @numbers;
}
print average(qw< 1 5 18 3 5>);
此代码先定义一个
average
子例程,在子例程中计算总和并除以元素数量得到平均值,最后调用该子例程并打印结果。
5、修复 C 风格 for 循环中的越界错误,并展示使用 Perl 风格 for/foreach 循环的更好方法。
修复 C 风格
for
循环中的越界错误,需将循环终止条件从
$i <= $num_elements
改为
$i < $num_elements
更好的方法是使用 Perl 风格的
for
/
foreach
循环,示例代码如下:
my @array = qw( fee fie foe fum );
for my $word (@array) {
print "$word";
}
这种循环能避免越界错误。
6、编写代码为 %stat_for 哈希中的键分配随机值,键为’strength’、’intelligence’、’dexterity’,随机值为 2 加上两个 1 到 6 的随机整数之和,且随机值不能小于 6,最后输出每个键及其对应的值。
my %stat_for;
my @stats = ('strength', 'intelligence', 'dexterity');
foreach my $stat (@stats) {
my $random = 2 + int(rand(6)) + int(rand(6));
redo if $random < 6;
$stat_for{$stat} = $random;
}
print <<"END_CHARACTER";
Strength: $stat_for{strength}
Intelligence: $stat_for{intelligence}
Dexterity: $stat_for{dexterity}
END_CHARACTER
7、创建一个完整的代码,为 %stat_for 哈希中的键分配随机值,条件是该值至少为 6,并打印结果。
my %stat_for;
my @stats = ('strength', 'intelligence', 'dexterity');
foreach my $stat (@stats) {
my $random;
do {
$random = 2 + int(rand(6)) + int(rand(6));
} while ($random < 6);
$stat_for{$stat} = $random;
}
print <<"END_CHARACTER";
Strength: $stat_for{strength}
Intelligence: $stat_for{intelligence}
Dexterity: $stat_for{dexterity}
END_CHARACTER
8、创建一个包含值 1 到 5 的数组 @first,创建它的引用,然后从该引用创建另一个数组 @second。打印这两个数组。
以下是实现该功能的 Perl 代码:
my @first = (1..5);
my $first_ref = @first;
my @second = @$first_ref;
print "@first
";
print "@second
";
上述代码首先创建了包含 1 到 5 的数组
@first
,接着创建了它的引用
$first_ref
,然后从引用创建了数组
@second
,最后打印了这两个数组。
9、根据给定的 $sales 哈希表,计算吉姆在周五的销售数量和总销售额,并打印结果。$sales 哈希表结构如下:{ friday => { jim => [ 1, 1, 5 ], mary => [ 2 ] } }
代码示例如下:
my $sales = { friday => { jim => [ 1, 1, 5 ], mary => [ 2 ] }, };
my $friday = $sales->{friday}{jim};
my $num_sales = @$friday;
my $total = 0;
$total += $_ foreach @$friday;
print "Jim had $num_sales sales, for a total of $total dollars
";
10、以两种不同的方式从 $score_for 哈希中提取 Jim 和 Mary 的分数并打印出来。
第一种方式:
my ( $jim, $mary ) = @$score_for{ qw{Jim Mary} };
print "$jim $mary";
第二种方式:
$jim = $score_for->{Jim};
$mary = $score_for->{Mary};
print "$jim $mary";
11、编写一个名为 average 的子程序,用于计算传入数字的平均值,并打印给定一组数字的计算结果。
以下是实现该功能的 Perl 代码:
sub average {
my $numbers = @_;
my $total = 0;
$total += $_ foreach @$numbers;
my $average = $total / scalar @$numbers;
return $average;
}
my @numbers = (1, 2, 3, 4, 5);
my $result = average(@numbers);
print $result;
上述代码定义了
average
子程序,它接收一组数字,计算其总和,然后除以数字的数量得到平均值并返回。最后,给定一组数字调用该子程序并打印结果。
12、编写一个名为make_multiplier的子程序,该子程序返回一个子程序,该返回的子程序将其输入乘以给定的数字。用不同的数字进行测试。
以下是实现该功能的Perl代码:
sub make_multiplier {
my $num = shift;
return sub {
my $input = shift;
return $input * $num;
};
}
my $times_seven = make_multiplier(7);
my $times_five = make_multiplier(5);
print 21 == $times_seven->(3) ? "yes
" : "no
";
print 20 == $times_five->(4) ? "yes
" : "no
";
代码中定义了
make_multiplier
子程序,它接受一个数字作为参数,并返回一个匿名子程序。这个匿名子程序接受一个输入数字,并将其乘以
make_multiplier
传入的数字。最后使用不同的数字进行了测试。
13、编写一个递归子例程 sum 来计算传入数字的总和,并打印给定一组数字的计算结果。
以下是一个递归子例程
sum
的示例代码:
sub sum {
my @numbers = @_;
if (@numbers == 0) {
return 0;
} else {
my $first = shift @numbers;
return $first + sum(@numbers);
}
}
my @given_numbers = (1, 2, 3, 4, 5);
print sum(@given_numbers);
这段代码定义了递归子例程
sum
,当传入数字为空时返回 0,否则取出第一个数字并递归调用
sum
计算剩余数字的和,最后将第一个数字与剩余数字的和相加。最后使用给定的一组数字调用该子例程并打印结果。
14、使用正则表达式从给定文本中提取员工姓名及其对应的编号,并以哈希形式打印结果。给定文本为:alice: 48472
bob:34582
we need to fire charlie
charlie : 45824
denise is a new hire
denise : 34553
可以使用以下代码实现:
use strict;
use warnings;
use Data::Dumper;
my $employee_numbers = <<'END_EMPLOYEES';
alice: 48472
bob:34582
# we need to fire charlie
charlie : 45824
# denise is a new hire
denise : 34553
END_EMPLOYEES
my %employee_number_for;
while ( $employee_numbers =~ /^ s* (w+) s* : s* (d{5}) s* $/gmx ) {
$employee_number_for{$1} = $2;
}
print Dumper \%employee_number_for;
执行上述代码后,输出结果如下:
$VAR1 = { 'alice' => '48472', 'denise' => '34553', 'charlie' => '45824', 'bob' => '34582' };
15、将命令行参数中的单词列表进行 UTF – 8 解码,将其拆分为字符,获取每个字符的 Unicode 码点并打印出来。
以下是实现该功能的代码示例:
use strict;
use warnings;
use Encode 'decode';
binmode STDOUT, ':encoding(UTF-8)';
foreach my $word (@ARGV) {
$word = decode('UTF-8', $word);
my @chars = split //, $word;
foreach my $char (@chars) {
$char = "U+" . uc sprintf "%04x", ord $char;
print "$char ";
}
print "
";
}
上述代码首先对命令行参数中的每个单词进行 UTF – 8 解码,然后将其拆分为字符,接着获取每个字符的 Unicode 码点并将其转换为
U+XXXX
的格式,最后进行打印。
16、对给定的十六进制数字按降序排序,并以十六进制格式输出结果。
可使用以下代码实现:
my @numbers = ( 0x23, 0xAA, 0xaa, 0x01, 0xfB );
my @sorted = sort { $b <=> $a } @numbers;
print join ', ' => map { sprintf '0x%X', $_ } @sorted;
输出结果为:
0xFB, 0xAA, 0xAA, 0x23, 0x01
17、使用grep的块形式和表达式形式,找出@numbers数组中的所有完全平方数,并按升序排序。同时,处理数组中包含非数字字符串的情况。
块形式:
my @numbers = ( 28, 49, 1000, 4, 25, 49, 529 );
my @squares = sort { $a <=> $b } grep { /^[0-9]+$/ && ( int(sqrt($_)) == sqrt($_) ) } @numbers;
print join ', ' => @squares;
表达式形式:
my @squares = sort { $a <=> $b } grep /^[0-9]+$/ && ( int(sqrt($_)) == sqrt($_) ), @numbers;
也可以写成:
my @squares = sort { $a <=> $b } grep(/^[0-9]+$/ && ( int(sqrt($_)) == sqrt($_)), @numbers);
这里使用正则表达式
/^[0-9]+$/
确保只处理正整数,从而处理数组中包含非数字字符串的情况。
18、从 @list 数组中移除重复元素,并返回一个包含唯一元素的新数组。
可以使用以下代码实现:
sub unique {
my @array = @_;
my %seen;
my @unique;
foreach my $element (@array) {
push @unique, $element unless $seen{$element}++;
}
return @unique;
}
my @list = qw( bob sally Andromalius sally bob ned Andromalius );
my @unique_list = unique(@list);
print join(', ', @unique_list); # 可添加此句打印结果以验证
19、过滤 @employees 数组,仅包含服务年限超过 1 年的员工,按姓氏排序,使用 map、sort 和 grep 创建一个包含他们全名的新数组。另外,使用 for 循环重写代码。
使用 map、sort 和 grep 的代码
my @employees = (
{ first_name => 'Sally', last_name => 'Jones', years => 4, payscale => 4, },
{ first_name => 'Abby', last_name => 'Hoffman', years => 1, payscale => 10, },
{ first_name => 'Jack', last_name => 'Johnson', years => 4, payscale => 5, },
{ first_name => 'Mr.', last_name => 'Magnate', years => 12, payscale => 1, },
);
my @names = sort { $a cmp $b} map { $_->{first_name} . ' ' . $_->{last_name}} grep { $_->{years} > 1} @employees;
foreach my $name (@names) {
print $name . "
";
}
使用 for 循环重写的代码
my @employees = (
{ first_name => 'Sally', last_name => 'Jones', years => 4, payscale => 4, },
{ first_name => 'Abby', last_name => 'Hoffman', years => 1, payscale => 10, },
{ first_name => 'Jack', last_name => 'Johnson', years => 4, payscale => 5, },
{ first_name => 'Mr.', last_name => 'Magnate', years => 12, payscale => 1, },
);
my @filtered_employees;
foreach my $employee (@employees) {
if ($employee->{years} > 1) {
push @filtered_employees, $employee;
}
}
my @sorted_employees = sort { $a->{last_name} cmp $b->{last_name}} @filtered_employees;
my @names;
foreach my $employee (@sorted_employees) {
push @names, $employee->{first_name} . ' ' . $employee->{last_name};
}
foreach my $name (@names) {
print $name . "
";
}
20、将 Convert::Distance::Metric 模块添加到 lib/ 目录并更新 MANIFEST 文件。
将模块文件
lib/Convert/Distance/Metric.pm
放置到
lib/
目录下,更新
MANIFEST
文件,使其包含以下内容:
Changes
lib/Convert/Distance/Imperial.pm
lib/Convert/Distance/Metric.pm
Makefile.PL
MANIFEST
README
t/00 – load.t
t/manifest.t
t/pod – coverage.t
t/pod.t
21、为 Convert::Distance::Metric 模块添加 POD 文档。
为简便起见,我们将在最后的
__END__
字面量之后添加 POD。如下:
__END__
=head1 NAME
Convert::Distance::Metric - Convert kilometers to meters and back
=head1 SYNOPSIS
use Convert::Distance::Metric ":all";
print kilometers_to_meters(7);
print meters_to_kilometers(3800);
=head1 DESCRIPTION
This is a simple module to convert kilometers to meters and back. It’s mainly here to show how modules are built and documented.
=head1 EXPORT
The following functions may be exported on demand. You can export all of them with: `use Convert::Distance::Metric ':all';`
=over 4
22、创建一个继承自 Person 类的 Customer 类,要求客户必须至少 18 岁。
以下是实现该功能的代码:
package Customer;
use Moose;
extends 'Person';
use Carp 'croak';
use namespace::autoclean;
sub BUILD {
my $self = shift;
if ( $self->age < 18 ) {
my $age = $self->age;
croak("Customers must be 18 years old or older, not $age");
}
}
__PACKAGE__->meta->make_immutable;
1;
23、使用Moose创建一个User类,包含用户名和密码属性,对密码进行哈希处理,并提供一个方法来检查给定的密码是否正确。测试该类。
以下是实现该功能的代码:
package User;
use Moose;
use Digest::MD5 'md5_hex';
use namespace::autoclean;
has username => ( is => 'ro', isa => 'Str', required => 1 );
has password => ( is => 'ro', isa => 'Str', writer => '_set_password',);
sub BUILD {
my $self = shift;
$self->_set_password(md5_hex($self->password));
}
sub password_eq {
my ( $self, $password ) = @_;
$password = md5_hex($password);
return $password eq $self->password;
}
__PACKAGE__->meta->make_immutable;
1;
# 测试代码
my $user = User->new( username => 'Ovid', password => 'Corinna',);
print $user->dump;
print "Yes" if $user->password_eq('Corinna');