Perl:在0和X,0和Y以及0和Z之间紧凑地写出三个循环

时间:2013-08-27 06:43:23

标签: perl

假设我有一个像这样的“make_members”方法。

sub make_members {  
    my ($number_members) = @_;
    my $rows = SomeDBIModule->select(); 
    my $count = @$rows;             
    for ( my $i = $count + 1; $i < $count + 1 + $number_members; $i++ ) {
          $rows->insert(
              name => "name".$i, 
              type => "A",
              created_at => time,                 
         );                    
   }                                                        
 } 

到目前为止一切顺利。现在想象一下该方法可以作为输入,用户数量类型a,类型b和类型c所需的:

sub make_members {  
    my ($number_members, $n_members_type_a, $n_members_type_b, $n_members_type_c) = @_;
    #....

写下这首先想到的是制作3个循环。第一个

     for ( my $i = $count + 1; $i < $count + 1 + $n_members_type_a; $i++ ){
          $rows->insert(
              name => "name".$i, 
              type => "A",
      #....

$ count + 1和$ n_members_type_b之间的第二个。 $ count + 1和$ n_members_type_c之间的第三个。

这看起来太长而且糟糕。 有没有更好的写作方式?

2 个答案:

答案 0 :(得分:2)

“三个或更多,请使用for”。

将其打包到另一个循环中

sub make_members {
  my %number_members_for_type;
  @number_members_for_type{qw/A B C/} = @_;
  my $rows = ...;
  while (my ($type, $num) = each %number_members_for_type) {
    for my $i ( @$rows + 1 .. @$rows + $num ) {
      $rows->insert(
        name => "name$i",
        type => $type,
        ...
      )
    }
  }
}

这假定它被称为make_members($n_type_a, $n_type_b, $n_type_c)

使用参数的哈希可以很好地扩展。

如果将哈希作为参数传递,我们可以概括这一点。如果name属性必须是唯一ID,插入只能由此函数完成,那么我们也可以优雅地管理它:

sub make_inserter {
  my ($rows) = @_;
  my $id_counter = @$rows;
  return sub {
    my %type2nums = @_;
    while (my ($type, $num) = each %type2nums) {
      for my $i ($id_counter + 1 .. $id_counter + $num) {
        $rows->insert(
          name => "name$i",
          type => $type,
          ...
        );
      }
      $id_counter += $num;
    }
  };
}

...

# Careful! Do not make an inserter for the same handle twice!
my $make_members = make_inserter(SomeDBIModule->select);
$make_members->(A => 2, B => 3);

如果键的顺序很重要,我们应该这样做,因为哈希键的顺序是未定义的:

  ... # as before
  return sub {
    while (my ($type, $num) = splice @_, 0, 2) {
      ... # as before
    }
  };

答案 1 :(得分:0)

对方法重复许多类似的参数通常表明可以进行一些简化。

因此,不要取一个数字列表,而是将类型作为参数接受:

sub make_members {  
    my ($number_members, $member_type) = @_;

以后:

$rows->insert(
              name => "name".$i, 
              type => $member_type,
              created_at => time,                 
         );

然后适当地调用代码。例如,创建x倍“A”,y乘以“B”,z乘以“C”:

%numbers_of = ( "A" => 4, "B" => 5, "C" => 2 );
for my $type (keys %numbers_of) {
    make_members( $numbers_of{ $type }, $type );
}