良いコードを参考にしましょう③

OpenWeatherMapを使用して、指定された日の12時の気温を取得するためのコードをどのようにして書くか。

自分が書いたコード。

#指定された日の12時の気温、最高気温、最低気温が入ったハッシュリファレンスを返すためのサブルーチンを作成。
sub return_temp{
    my ($api_data, $date) = @_;
    unless (defined($api_data)){
        print "API data is not defined.\n";
        return undef;
    }
    my $date_12pm = $date." 12:00:00";
    my $key;


#12時の気温の取得。
    my $temp_12 = 'undef';
    foreach $key(keys $api_data->{'list'}){
        my $dt_txt_phr = $api_data->{'list'}->[$key]->{'dt_txt'};
        if ($dt_txt_phr) {
            if ($dt_txt_phr =~ /$date_12pm/){
                $temp_12 = $api_data->{'list'}->[$key]->{'main'}->{'temp'};
            }
        }
    }

他の人が書いたコード。

sub get_temp_at_noon {
    my ( $json, $date ) = @_;
    return undef if( !$json );

    my $content = decode_json( $json );
    my $hour    = "12:00:00";

    my ($noon) = grep { $_->{dt_txt} =~ /$date $hour/ } @{ $content->{list} };
    
    if( $noon->{main}->{temp} ) {
        return $noon->{main}->{temp};
    }
    return undef;
}

JSONデータが定義されていない時undefを返すためのコードは、

 unless (defined($api_data)){
        return undef;
    }

上記のように書くより、次のように書いた方がコンパクトでわかりやすい。

return undef if( !$json );




最高気温と最低気温を取得する処理。

sub get_temp_maxmin {
    my ( $json, $date ) = @_;
    return undef if( !$json );

    my $content = decode_json( $json );
    my @temps   = grep { $_->{dt_txt} =~ /$date/ } @{ $content->{list} };

    my $maxmin = {};
    $maxmin->{max} = ( sort map { $_->{main}->{temp_max} } @temps )[-1];
    $maxmin->{min} = ( sort map { $_->{main}->{temp_min} } @temps )[0];

    if( $maxmin->{max} && $maxmin->{min} ) {
        return $maxmin;
    }
    return undef;
}

ハッシュを作らずいきなりハッシュのリファレンスを作成している。
@tempsの要素を1つずつmapで処理していて、その戻り値のリストをsortで並べ替え一番最後の値を返している。