减少代码的冗长和效率

时间:2015-06-17 21:50:14

标签: perl

我在下面看到了一些繁重的规定,最后我们得到了一些@hits,我们只需要返回一个:

if ($#hits > 0)
{
    my $highestScore = 0;
    my $chosenMatch = "";
    for $hit (@hits)
    {
        my $currScore = 0;
        foreach $k (keys %{$hit})
        {
            next if $k eq $retColumn;
            $currScore++ if ($hit->{$k} =~ /\S+/);
        }

        if ($currScore > $highestScore)
        {
            $chosenMatch = $hit;
            $highestScore = $currScore;
        }
    }
    return ($chosenMatch);
}
elsif ($#hits == 0)
{
    return ($hits[0]);
}

我的眼睛已经满了,我希望简化上面的代码,我想出了:

return reduce {grep /\S+/, values %{$a} > grep /\S+/, values %{$b} ? $a : $b} @matches;

使用课程后useList::Util

我想知道简洁版本是否比原版本有效和/或优势。此外,还有一个条件被跳过:if $k eq $retColumn,我怎样才能有效地将其传入?

2 个答案:

答案 0 :(得分:4)

  

我想知道简洁版本是否比原版本有效和/或优势

简洁版的效率低于原版,因为它会计算每个元素的得分两次,但它确实具有可读性优势。

以下内容保持了可读性增益(甚至增加了一些):

sub get_score {
   my ($match) = @_;
   my @keys = grep { $_ ne $retColumn } keys %$match;
   my $score = grep { /\S/ } @{$match}{ @keys };
   return $score;
}

return reduce { get_score($a) > get_score($b) ? $a : $b } @matches;

您可以查看该子组件的任何部分并在不环顾四周的情况下理解它。您需要理解代码的最少上下文,它的可读性就越高。

如果确实需要提高效率,可以避免使用Schwartzian变换在每次输入上调用get_score两次。与许多优化一样,您将获得可读性,但至少它是惯用的(众所周知且因此可识别)。

return
   map { $_->[0] }
   reduce { $a->[1] > $b->[1] ? $a : $b }
   map { [ $match, get_score($match) ] }
   @matches;

答案 1 :(得分:4)

有一句名言:

  

“过早优化是所有邪恶的根源” - 唐纳德克努特

几乎总是如此,使代码更简洁实际上并没有对效率产生太大影响,并且可能会对可读性和可维护性造成重大损失。

算法很重要,代码布局......不是真的。像reducemapgrep之类的东西仍在循环中 - 他们只是在幕后这样做。使用它们几乎没有效率,你刚刚在文件中保存了一些字节。如果它们使您的代码更清晰,那就没问题,但这应该是您最重要的考虑因素。

请 - 先保持清醒,始终保持清醒。让你的算法变得更好。不要担心用grepmap替换显式循环,除非这些事情使您的代码更清晰。

为了建设性的利益:

  • 使用strictwarnings非常重要。真的非常重要。

回答你原来的问题:

  

我想知道简洁版本是否比原版本有效和/或优势

不,我认为如果有相反的事情。除了分析代码速度之外,经验法则是查看循环的数量和大小 - 单个代码块很少有很大差异,但运行它很多次(不必要地)是你效率低下的地方。

在您的第一个示例中 - 您有两个循环,foreach循环内的for循环。看起来您遍历了@hits数据结构一次,然后“打开”它以获取内层。

在您的第二个示例中,您的grep都是循环,而您的reduce也是。如果我正确地阅读它,那么它将多次遍历您的数据结构。 (因为您grep values $a$b - 这些将会多次应用。)

因此,我不认为你通过做你所做的事情已经获得了可读性或效率。但是你已经做了一个功能,这将使未来的维护程序员必须非常努力地思考。采取另一个引用:

  

“每个人都知道调试的速度是编写程序的两倍。所以,如果你在编写程序时就像你一样聪明,那么你将如何调试呢?” - Brian Kernighan