August 10, 2006
my @a = qw(foo bar baz);こんな配列から
?,?,?という文字列を使いたい場合があります。
例えば、
SELECT * FROM hoge WHERE user_id IN (?,?,?);みたいな SQL にする場合のプレースホルダを作ると言った具合に。
社内 IRC で、clouder さんが言い出して、
18:27 <clouder>join(',', map('?', @a))と言う。
18:27 <clouder> こんなのしか思いつかない。。
まぁ、それが妥当というか、普通それが思い浮かぶよなーって思ってたら、会社の dos さんという人が
19:15 <dos> '?,' x @a; で s/,$//; というソリューションとか、異様なことを言い出した。
sub placeholder_from_array {
return join(',', map('?', @_));
}
こんなのと
sub placeholder_from_array {
(my $str = ('?,' x @_)) =~ s/,$//;
return $str;
}
こんなのでベンチマークを取ってみると、後者のほうが倍以上速い。やべ。ずっと前者でやってたけど全部後者に書き換えたくなってきた。
こういう些細なことでも「いかにも perl らしい」方法で、より高速に動くというのは素敵です。
ただ、まぁ、ぶっちゃけ
「前者は 2.42 μ秒かかったけど後者は 0.95 μ秒で済んだ」
だから、「一回の処理で数万回この処理を通る」とかじゃないなら、可読性や保守性の高い前者を取りますけどねw
追記:
sub placeholder_from_array {
chop(my $str = ('?,' x @_));
return $str;
}
置換するより chop() したほうが更に速いかも。更に追記:
sub placeholder_from_array {
return substr('?,' x @_, 0, -1);
}
いやー、これのが速い。最初のやつより 5 倍ぐらい速い。。。