【问题标题】:Perl - CodeGolf - Nested loops & SQL insertsPerl - CodeGolf - 嵌套循环和 SQL 插入
【发布时间】:2010-12-24 23:34:15
【问题描述】:

我必须制作一个非常小而简单的脚本,根据这些标准用字符串值填充表格:

  • 2 个字符长
  • 第一个字符始终是数字 (0-9)
  • 第二个字符是(0-9),但也包括“X”
  • 需要将值插入到数据库的表中

程序将执行:

insert into table (code) values ('01');
insert into table (code) values ('02');
insert into table (code) values ('03');
insert into table (code) values ('04');
insert into table (code) values ('05');
insert into table (code) values ('06');
insert into table (code) values ('07');
insert into table (code) values ('08');
insert into table (code) values ('09');
insert into table (code) values ('0X');

以此类推,直到总共插入 110 个值。

我的代码(只是为了完成它,而不是为了最小化和提高效率)是:

use strict;
use DBI;
my ($db1,$sql,$sth,%dbattr);
%dbattr=(ChopBlanks => 1,RaiseError => 0);
$db1=DBI->connect('DBI:mysql:','','',\%dbattr);
my @code;
for(0..9)
{
    $code[0]=$_;
    for(0..9)
    {
        $code[1]=$_;
        insert(@code);
    }
    insert($code[0],"X");
}
sub insert
{
    my $skip=0;
    foreach(@_)
    {
        if($skip==0)
        {
            $sql="insert into table (code) values ('".$_[0].$_[1]."');"; 
            $sth=$db1->prepare($sql); 
            $sth->execute();
            $skip++;
        }
        else
        {
            $skip--;
        }
    }
}
exit;

我只是想看看这个逻辑的真正简洁和精确的版本。

【问题讨论】:

  • Perl、Ruby、Python 和 PHP - 唯一适用于带有数据库的高尔夫的语言......这还不够......主题太具体了。

标签: perl performance foreach code-golf nested-loops


【解决方案1】:

133 个字符 - 非严格

use DBI;$d=DBI->connect('DBI:mysql','','',{RaiseError=>1});for$a(0..9){for$b(0..9,'X'){$d->do("insert into table values('$a$b')");}}

152 个字符 - 严格

use strict;use DBI;my$d=DBI->connect('DBI:mysql','','',{RaiseError=>1});for my$a(0..9){for my$b(0..9,'X'){$d->do("insert into table values('$a$b')");}}

152个字符串的易读版本:

use strict;use DBI;
my $d=DBI->connect('DBI:Informix:stores','','',{RaiseError=>1});
foreach my $a (0..9)
{
    foreach my $b (0..9, 'X')
    {
        $d->do("insert into table values('$a$b')");
    }
}

思考过程

给定:

create table table(code char(2) not null);

还有 Perl:

use strict;
use DBI;
my $d=DBI->connect('DBI:mysql','','',{RaiseError=>1});
my $h=$d->prepare("insert into table(code)values(?)");
foreach my $a (0..9)
{
    foreach my $b (0..9, 'X')
    {
        $h->execute("$a$b");
    }
}

我用 Informix 进行了测试,所以我实际使用的连接字符串是“DBI:Informix:stores”。

这个解决方案仍然是可读的 - 因为 RaiseError,所以是防错的(除非你也想添加一个事务)。

代码打高尔夫球,它变成(182 个字符):

use strict;use DBI;my$d=DBI->connect('DBI:mysql','','',{RaiseError=>1});my$h=$d->prepare("insert into table(code)values(?)");for my$a(0..9){for my$b(0..9,'X'){$h->execute("$a$b");}}

【讨论】:

  • 我已经习惯了添加严格,我什至没有停下来问为什么。 - 所以...它有什么用(简而言之)?
  • use strict; 被专家用来确保他们没有犯愚蠢的错误; use strict; 被初学者忽略,因为他们没有意识到这会阻止他们犯错。但是当你在打代码时,每个字节都很重要,所以use strict; 与“代码高尔夫球”是对立的;多字符名称也是如此。这必须接近最低限度;严格版本中有 6 个必要的空格(非严格版本中有 4 个)。连接中可以省略属性哈希;这将节省更多空间(我相信 16 个字节),但我不喜欢放弃所有错误检测。
  • 愚蠢的错误,例如“在第 7 行缺少分号”或在 if 比较中使用一个“=”等号?
  • 是的,就像那些 - 或变量名中的拼写错误,或许多其他。实际上,其中一些是由use warnings;而不是use strict;处理的,后者更多的是关于滥用字符串作为引用......
  • @JL - 是的,我注意到您也删除了一些 db connect 属性。如果我没记错的话,您也可以在执行参数 vars 周围加上引号并在其中添加一个逗号
【解决方案2】:

第一部分可以简化为

for my $x (0..9) {
  for my $y (0..9,'X') {
    insert("$x$y");
  }
}

我真的不明白 $skip 在第二部分做了什么。我会的

sub insert {
  my $code = shift;
  my $sql="insert into table (code) values ('$code');"; 
  my $sth=$db1->prepare($sql); 
  $sth->execute();
}

【讨论】:

  • 没有跳过,每行会打印两次
  • 哦,谢谢第一部分 - 我从来不知道你可以构造这样的语句
  • 当您在二元素数组上使用 foreach(@_) 时,它只会打印两次。通过避免这种情况,您还可以避免使用$skip;
【解决方案3】:

您可以在 sql 中执行(对于某些 sql 值):

insert into table (code) select concat(foo, bar)
from (select 0 foo union select 1 union select 2 union select 3 union select 4
    union select 5 union select 6 union select 7 union select 8 union select 9)
    foo
join (select 0 bar union select 1 union select 2 union select 3 union select 4
    union select 5 union select 6 union select 7 union select 8 union select 9
    union select 'X')
    bar;

【讨论】:

  • 这很好 - 没想到会这样
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多