优化perl代码

时间:2014-08-25 05:21:15

标签: perl

我必须写入检查数组ref超过3个参数。如果值来自一个数组,那么我已经编写了一个foreach循环,然后将其切断并在连接管道后分配给一个新变量。

代码

if ( defined $args->{hotel} ) {
    if ( ref( $args->{hotel} ) eq "ARRAY" ) {
        foreach my $hotel ( @{ $args->{hotel} } ) {
            $hotel .= $hotel . "|";
        }
        chop($hotel);
        $args->{hotel_name} = $hotel;
    } else {
        $args->{hotel_name} = $args->{hotel};
    }
} else {
    $args->{hotel_name} = $hotel;
}
if ( defined $args->{country} ) {
    if ( ref( $args->{country} ) eq "ARRAY" ) {
        foreach my $country_name ( @{ $args->{country} } ) {
            $country_name .= $country_name . "|";
        }
        chop($country_name);
        $args->{country_name} = $country_name;
    } else {
        $args->{country_name} = $args->{country};
    }
} else {
    $args->{country_name} = $country_name;
}
if ( defined $args->{city} ) {
    if ( ref( $args->{city} ) eq "ARRAY" ) {
        foreach my $city ( @{ $args->{city} } ) {
            $city .= $city . "|";
        }
        chop($city);
        $args->{city_name} = $city;
    } else {
        $args->{city_name} = $args->{city};
    }
} else {
    $args->{city_name} = $city;
}

我想为这种工作编写一个函数,这样就不会重复相同的代码。请帮我;我们怎样才能在Perl中做到这一点?

2 个答案:

答案 0 :(得分:5)

你可以写:

sub convert_to_name ($$) {  # ($value, $fallback_name)
    my ($value, $fallback_name) = @_;
    if (defined $value) {
        if (ref($value) eq 'ARRAY') {
            return join '|', @$value;
        } else {
            return "$value";
        }
    } else {
        return $fallback_name;
    }
}

$args->{'hotel_name'} = convert_to_name $args->{'hotel'}, $hotel;
$args->{'country_name'} = convert_to_name $args->{'country'}, $country;
$args->{'city_name'} = convert_to_name $args->{'city'}, $city;

答案 1 :(得分:4)

您的代码中似乎存在一些潜在的错误,最重要的是在较低范围内重用变量名称。

但是,当然您可以在代码中添加迭代循环,这样就不需要3个几乎相同的部分。以下是通过创建中间散列数据结构以将字段名称与值相关联来实现的。

注意:如果您的第一个if语句使所有ifs处于同一级别,我也会通过反转逻辑来简化代码。此外,使用join而不是滚动自己的功能是有意义的。

my %hash = (
    hotel   => $hotel,
    country => $country_name,
    city    => $city,
);

while ( my ( $field, $value ) = each %hash ) {
    if ( !defined $args->{$field} ) {
        $args->{"${field}_name"} = $value;

    } elsif ( ref( $args->{$field} ) eq "ARRAY" ) {
        $args->{"${field}_name"} = join '|', @{ $args->{$field} };

    } else {
        $args->{"${field}_name"} = $args->{$field};
    }
}

此外,如果您对条件运算符感到满意,可以进一步减少这种情况。但是,有些人会认为这太混乱了:

while ( my ( $field, $value ) = each %hash ) {
    $args->{"${field}_name"} = !defined $args->{$field}
        ? $value
        : ref( $args->{$field} ) eq "ARRAY"
        ? join( '|', @{ $args->{$field} } )
        : $args->{$field};
}