簡體   English   中英

有條件地將元素包括在列表中的最佳方法是什么?

[英]What's the best way to conditionally include an element in a list?

可能的方式:

  1. 使用push

     my @list; push @list, 'foo' if $foo; push @list, 'bar' if $bar; 
  2. 使用條件運算符

     my @list = ( $foo ? 'foo' : (), $bar ? 'bar' : (), ); 
  3. 使用x!! 布爾列表壁球運算符

     my @list = ( ('foo') x!! $foo, ('bar') x!! $bar, ); 

哪一個更好,為什么?

好吧,他們都做不同的事情。

但是,在所有其他因素都相同的情況下,

push @list, 'foo' if $foo;

是最直接傳達其含義的語句,因此應首選。

如果您不得不停下來想一想應該執行與推送數組元素一樣簡單的語句,那么您在做錯了什么。

my @list = (
    $foo ? 'foo' : (),
    $bar ? 'bar' : (),
);

如果這是在其他地方進行的一些巨大初始化的一部分,則可以確定。

我認為使用

my @list = (
    ('foo') x!! $foo,
    ('bar') x!! $bar,
); 

表示程序員擁有- 我該如何放置? - 問題

順便說一句,沒有所謂的x!! 復合運算符。 !! 雙重邏輯否定 它將任意的false值轉換為已定義但為false的值(空字符串),該值在perl需要數字的地方使用時將產生0 真值將轉換為1 在這里!! $foo$bar並將其編寫為x!! $foo x!! $foo不必要地混淆了代碼的含義。

x重復運算符 所以,

 ('foo') x !!$foo;

表示一次重復('foo')一次,這取決於$foo是true還是false

PS:當然,結果是有一篇PerlMonks文章介紹了所謂的布爾列表壁球運算符 我閱讀了這篇文章 ,發現它沒有說服力。

我想建議我對“可讀”方法進行配音:

sub maybe ($$) { $_[1] ? $_[0] : () }

my @list = (
  maybe("foo", $foo),
  maybe("bar", $bar),
);

它有許多所謂的x!!的好處x!! 運算符(雖然稍長一些),但是有了額外的好處,您稍后可以真正理解您的代碼。

編輯:原型不能幫助Perl更好地解析,也不能讓我們放棄括號,它只是防止Perl做我們不想要的事情。 如果要拋棄父母,我們必須做一些工作。 這是不帶括號的替代版本:

sub maybe {
  my($var, $cond, @rest) = @_;
  return @rest unless $cond;
  return $var, @rest;
}

my @list = (
  maybe "foo", $foo,
  maybe "bar", $bar,
);

無論我們使用原型做什么,Perl都將嘗試將其解析為maybe("foo", $foo, maybe("bar", $bar)) ,因此,如果我們想拋開括號,我們只需要使它成為括號即可。給出正確的結果。

盡管OP並沒有要求這樣做,但是這個問題為我提供了use Benchmark;的很好的借口use Benchmark;

這是代碼:

use strict;
use warnings;
use Benchmark qw( cmpthese);

my $foo = 1;
my $bar = "true";

cmpthese( -10, {
  "push" => sub {
      my @list;
      push @list, 'foo' if $foo;
      push @list, 'bar' if $bar;
  },
  "?::" => sub {
      my @list = (
        $foo ? 'foo' : (),
        $bar ? 'bar' : ()
      );
  },
  "x!!" => sub {
      my @list = (
        ('foo') x!! $foo,
        ('bar') x!! $bar
      );
  }
});

以下是一些典型結果:

         Rate  x!!  ?:: push
x!!  646539/s   --  -8% -12%
?::  701429/s   8%   --  -5%
push 736035/s  14%   5%   --

鑒於brian d foy對Benchmark的不確定性的估計7% ,顯然push似乎是最快的增長方式。

加起來:

$need4speed ? do { push @like $this} : try { something('less' x!! $obfuscated) };
# DISCLAIMER: This is not valid code

我個人使用$foo ? 'foo' : () $foo ? 'foo' : ()在這種情況下,因為很明顯(與('foo') x!! $foo ),不需要特別的努力就可以理解(與('foo') x !!$foo比較('foo') x !!$foo ),並且可以在列表上下文中使用(與push @list, 'foo' if $foo; )。

但是,當然,答案取決於您選擇哪種標准來選擇最佳選項。 如果通過混淆比較它們,則('foo') x!! $foo ('foo') x!! $foo一定會贏。 如果比較笨拙, push @list, 'foo' if $foo; 將是第一個。 還是您的意思是性能? 我猜不會 :-)

但是,如果按風格比較它們,我的選擇是$foo ? 'foo' : () $foo ? 'foo' : ()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM