【问题标题】:Perl: How to add additional column to each row in multi-dimensional arrayPerl:如何向多维数组中的每一行添加额外的列
【发布时间】:2021-05-06 14:19:35
【问题描述】:

我有两个多维数组:array1(@wipr) 和 array2(@widesc)

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
  
# Initializing and defining the array
my @wipr = ( ['1111', '2221'],
              ['1112', '2222'],
              ['1113', '2223'],
              ['1115', '2225'],
              ['1113', '2224'] );
my @widesc = ( ['1111', 'Bug1'],
              ['1112', 'Feature1'],
              ['1113', 'Feature2'],
              ['1114', 'Feature2'] );
# Printing items from the array
#print Dumper(\@wipr);
#print Dumper(\@widesc);

# Using For loop
for(my $m = 0; $m <= $#wipr; $m++)
{   
   for(my $n = 0; $n <= $#widesc ; $n++)
   {  
      #print $wipr[$m][0], "\n";
      #print $widesc[$n][0];
      if ( "$wipr[$m][0]" == "$widesc[$n][0]" )
      {
          print "Matches: $wipr[$m][0] == $widesc[$n][0]";
          my $desc="$widesc[$n][1]";
          print "desc value is : $desc";
          #push(@{$wipr[$m][1][$m]},"$desc");
          #print "$wipr[$m][1][$m]";
          $wipr[$m][1][$m] = "'$desc'";
          #push (@wipr,$wipr[$m][1][$m]);
      }
      #else
      #{
        #  print "Doesn't Matches: $wipr[$m][0] == $widesc[$n][0]";
      #}
   }  
   print "\n";  
} 
print Dumper(\@wipr);

如果 array1(@wipr) 中第一列的值与 array2(@widesc) 中第一列的值匹配,我们需要将 array2 的第二个元素添加到 array1 中。 如果值不匹配,它应该只输入一个字符串“未找到”

要求的输出应该是:

 my @result= ( ['1111', '2221', 'Bug1'],
                  ['1112', '2222', 'Feature1'],
                  ['1113', '2223', 'Feature2'],
                  ['1115', '2225', 'Not Found'],
                  ['1113', '2224', 'Feature2'] );

我在 array1 中添加第三列时遇到了困难。你能帮忙吗?

错误:在arrays1.pl line33 使用“strict refs”时不能使用字符串(“2221”)作为数组引用。

【问题讨论】:

  • push( @{$wipr[$m]}, $desc );$wipr[$m][2] = $desc;
  • 我希望将其添加为第三列。我看到的错误是“不能使用字符串(“2221”)作为数组引用,而在 arrays1.pl line33 处使用“严格引用”。
  • 第 33 行似乎是:$wipr[$m][1][$m] = "'$desc'";@wipr 是一个数组。 @wipr[$m] 是一个数组。 $wipr[$m][1] 是一个字符串。 @wipr[$m][1] 不是数组。所以索引它是没有意义的。
  • 感谢 jhnc。这是解决的。 # Using For loop for(my $m = 0; $m &lt;= $#wipr; $m++) { for(my $n = 0; $n &lt;= $#widesc ; $n++) { #print $wipr[$m][0], "\n"; #print $widesc[$n][0]; if ( "$wipr[$m][0]" == "$widesc[$n][0]" ) { print "Matches: $wipr[$m][0] == $widesc[$n][0]"; my $desc="$widesc[$n][1]"; print "desc value is : $desc"; #push(@{$wipr[$m][1][$m]},"$desc"); #print "$wipr[$m][1][$m]"; $wipr[$m][1][$m] = "'$desc'"; #push (@wipr,$wipr[$m][1][$m]); }

标签: perl


【解决方案1】:

天真的方式:

my @result;
for my $wipr (@wiprs)
   my $wi1 = $wipr->[0];

   for my $widesc (@widescs)
      my $wi2 = $widesc->[0];
      if ($wi1 == $wi2) {
         push @result, [ $wi1, $wipr->@[1..$#$wipr],  $widesc->@[1..$#$widesc] ];
         last;
      }
   }
}

这很慢。如果有N个WI,则执行内循环N*N/2次。这意味着所花费的时间与 N2 的平方成正比。

当某事物占用与 N2 的平方成正比的资源(例如时间)时,我们说它是 O(N2)。


上面这么慢的原因是匹配记录的过程。如果数组是排序的呢?

@wiprs   = sort { $a->[0] <-> $b->[0] } @wiprs;
@widescs = sort { $a->[0] <-> $b->[0] } @widescs;

my $pr_i = 0;
my $desc_i = 0;

my @results;
while ($pr_i < @wiprs && $desc_i < @widescs) {
   my $wipr   = $wiprs[$pr_i];
   my $widesc = $widescs[$desc_i];

   my $wi1 = $wipr->[0];
   my $wi2 = $wipdesc->[0];

   my $cmp = $wi1 <=> $wi2;
   if ($cmp < 0) {
      ++$pr_i;
   }
   elsif ($cmp > 0) {
      ++$desc_i;
   }
   else {
      push @result, [ $wi1, $wipr->@[1..$#$wipr],  $widesc->@[1..$#$widesc] ];
      ++$pr_i;
      ++$desc_i;
   }
}

这是 O(N log N)。好多了很多

如果我们假设有两个数组具有相同的 WI,则上述简化为:

die "Bad data\n" if @wiprs != @widescs;

@wiprs   = sort { $a->[0] <-> $b->[0] } @wiprs;
@widescs = sort { $a->[0] <-> $b->[0] } @widescs;

my $pr_i = 0;
my $desc_i = 0;

my @results;
while ($pr_i < @wiprs && $desc_i < @widescs) {
   my $wipr   = $wiprs[$pr_i];
   my $widesc = $widescs[$desc_i];

   my $wi1 = $wipr->[0];
   my $wi2 = $wipdesc->[0];

   die "Bad data\n" if $wi1 != $wi2;

   push @result, [ $wi1, $wipr->@[1..$#$wipr],  $widesc->@[1..$#$widesc] ];
   ++$pr_i;
   ++$desc_i;
}

当然,如果数组已经排序,则简化为以下 O(N) 解决方案:

die "Bad data\n" if @wiprs != @widescs;

my $pr_i = 0;
my $desc_i = 0;

my @results;
while ($pr_i < @wiprs && $desc_i < @widescs) {
   my $wipr   = $wiprs[$pr_i];
   my $widesc = $widescs[$desc_i];

   my $wi1 = $wipr->[0];
   my $wi2 = $wipdesc->[0];

   die "Bad data\n" if $wi1 != $wi2;

   push @result, [ $wi1, $wipr->@[1..$#$wipr],  $widesc->@[1..$#$widesc] ];
   ++$pr_i;
   ++$desc_i;
}

最后,我们通过先建一个索引,得到一个没有上述假设的 O(N) 解。

my %widescs_lookup;
for my $widesc (@widescs)
   my $wi = $widesc->[0];
   $widescs_lookup{$wi} = $widesc;
}

my @results;
for my $wipr (@wiprs)
   my $wi = $wipr->[0];

   my $wi_desc = $widescs_lookup{$wi}
      or next;

   push @result, [ $wi1, $wipr->@[1..$#$wipr],  $widesc->@[1..$#$widesc] ];
}

【讨论】:

  • 非常感谢 ikegami。抱歉,我刚刚更新了我的问题。我在array1 中添加了另一个元素。对于元素 ['1115', '2225'],它的第一个值与第二个数组元素不匹配。但是,我们应该有不匹配的数组元素,添加一个字符串。像 ['1115', '2225', '未找到']。
  • 将上述任何解决方案适应该场景非常容易。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-19
  • 1970-01-01
  • 2022-08-18
  • 2016-08-09
  • 2021-07-12
  • 2019-11-19
相关资源
最近更新 更多