Perl - CodeGolf - Вложенные циклы и вставки SQL - PullRequest
0 голосов
/ 25 декабря 2010

Мне пришлось сделать очень маленький и простой скрипт, который бы заполнял таблицу строковыми значениями в соответствии с этими критериями:

  • длина 2 символа
  • 1-й символ всегда числовой (0-9)
  • 2-й символ (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;

Мне просто интересно увидеть действительно лаконичную и точную версию этой логики.

Ответы [ 3 ]

1 голос
/ 25 декабря 2010

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");}}
1 голос
/ 26 декабря 2010

Вы можете просто сделать это в 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;
1 голос
/ 25 декабря 2010

Первая часть может быть уменьшена до

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();
}
...