我有一个类型的数据 -
500 3.6673656
----------
1000 3.2707536
----------
1500 3.2356145
----------
2000 3.0495141
----------
2500 3.016674
Run Code Online (Sandbox Code Playgroud)
即时间和距离.我需要将时间分成一个数组,将距离分成另一个数组.通过使用my @line = split( /\s+/, $_);我可以将距离存储在一个数组中,但不能存储时间.有没有其他方法可以将它们分别存储在不同的数组中?
输入来自文件,内容存储在@array.
我的剧本:
foreach $_ (@array){
if($_ =~ /[@]/) {# do nothing, it's a comment or formatting line}
else {my @line = split( /\s+/, $_);
print "@line\n";}
}
Run Code Online (Sandbox Code Playgroud)
让我们得到所有花哨的裤子:
#! /usr/bin/env perl
#
use strict;
use warnings;
use feature qw(say);
my @array;
while ( my $line = <DATA> ) {
chomp $line;
push @array, $line;
}
#
# As two separate arrays (Not so good)
#
my @times;
my @distances;
for my $entry ( @array ) {
chomp $entry; # Not needed, but never hurts
next if $entry =~ /--+$/; # Next if all dashes
my ( $distance, $time ) = split /\s+/, $entry;
push @times, $time;
push @distances, $distance;
}
say "The first entry as two distinct arrays";
say "Distance: $distances[0]";
say "Time: $times[0]";
#
# As two entries in a single array
#
my @velocities;
for my $entry ( @array ) {
chomp $entry; # Not needed, but never hurts
next if $entry =~ /--+$/; # Next if all dashes
my @velocity = split /\s+/, $entry;
push @velocities, \@velocity;
}
say "The first entry as an array of arrays";
say "Distance: " . $velocities[0]->[0];
say "Time: " . $velocities[0]->[1];
#
# As a hash in an array (Better Still)
# Note: Using regular expression to split
#
my @velocities2;
for my $entry ( @array ) {
chomp $entry; # Not needed, but never hurts
next unless $entry =~ /\s*(\S+)\s+(\S+)/;
my %velocity;
$velocity{DISTANCE} = $1;
$velocity{TIME} = $2;
push @velocities2, \%velocity;
}
say "The first entry as an array of hashes";
say "Distance: " . $velocities2[0]->{DISTANCE};
say "Time: " . $velocities2[0]->{TIME};
#
# As objects (The best!)
#
my @velocities3;
for my $entry ( @array ) {
chomp $entry; # Not needed, but never hurts
next unless $entry =~ /\s*(\S+)\s+(\S+)/;
my $distance = $1;
my $time = $2;
my $velocity = Local::Velocity->new( $distance, $time );
push @velocities3, $velocity;
}
say "The first entry as an object";
say "Distance: " . $velocities3[0]->distance;
say "Time: " . $velocities3[0]->time;
package Local::Velocity;
sub new {
my $class = shift;
my $distance = shift;
my $time = shift;
my $self = {};
bless $self, $class;
$self->distance( $distance );
$self->time( $time );
return $self;
}
sub distance {
my $self = shift;
my $distance = shift;
if ( defined $distance ) {
$self->{DISTANCE} = $distance;
}
return $self->{DISTANCE};
}
sub time {
my $self = shift;
my $time = shift;
if ( defined $time ) {
$self->{TIME} = $time;
}
return $self->{TIME};
}
package main;
__DATA__
500 3.6673656
----------
1000 3.2707536
----------
1500 3.2356145
----------
2000 3.0495141
----------
2500 3.016674
Run Code Online (Sandbox Code Playgroud)
第一种方式是你问的:两个并行数组.此方法的问题在于您现在必须按顺序保留两个单独的数据结构.如果传递时间和距离,则必须传递两个单独的数据元素.如果修改一个,则必须修改另一个.如果你push或pop一个人,你必须对另一个人这样做.
只有两个,但不是太糟糕,但想象一下,十几个或更多.
第二种方式使用References.引用允许您执行更复杂的数据结构.这将两个条目保持在一个阵列中.现在,您有一个包含两个条目的数组.push一个,你push就是另一个.pop一个,你pop就是另一个.如果将时间和距离传递给子程序,则只需传递一个条目.
第三种方式将参考概念提升了一个档次.您可以使用哈希,而不是使用数组来存储您的两个值.优点是散列中的每个元素都有一个名称.第一个入口或第二个入口是距离吗?没关系,这是标记的条目DISTANCE.与数组或数组相同的优点,但现在,您标记哪个是哪个.想象一个有姓名,电话,地址等的人,你可以看到这个优势.
最后一种方法是使用对象.您可以看到与使用哈希非常相似.您没有哈希或数组.您有一个Local::Velocity包含时间和距离的对象.
它似乎有点复杂,但对象有很多优点:
DISTANCE,Distance或者distance,并且没有拼写错误的问题是没有问题的distanse.你有一个叫做的方法distance.搞清楚这个名字,你的程序尽职尽责地崩溃,而不是继续处理糟糕的数据.velocity来获取对象并返回速度.或许您可能想要为速度添加方向.修改对象不会影响您的程序.面向对象的Perl允许您创建极其复杂的数据类型,而无需记住您如何构建它们.这就是为什么大多数新模块都是面向对象的.
拆分线和存储数据是微不足道的.您希望如何存储它以供以后使用是个问题.您可以在空格上拆分线并将其存储为:
my @data = map { [ split ] } @lines;
Run Code Online (Sandbox Code Playgroud)
默认调用split,拆分 $_空格.
接下来,您可以'@'使用grep 省略这些行:
my @data = map { [ split ] } grep { index( $_, '@' ) == -1 } @lines;
Run Code Online (Sandbox Code Playgroud)
这里只是最简单的存储结构:
use strict;
use warnings;
use constant TIME => 0;
use constant DISTANCE => 1;
my @data = map { [ split ] } grep { index( $_, '@' ) == -1 } @lines;
Run Code Online (Sandbox Code Playgroud)
然后,您可以按插槽名称处理不同的字段.
foreach my $row ( @data ) {
printf "At time : %d, distance was %f\n", $row->[TIME], $row->[DISTANCE];
}
Run Code Online (Sandbox Code Playgroud)