【问题标题】:Perl: Rearrange array based on element valuePerl:根据元素值重新排列数组
【发布时间】:2016-07-26 22:55:08
【问题描述】:

重新排列数组元素以使它们按相应的索引值(减一)排序和放置的最有效方法是什么? $dat 变量是元素的最大数量(在数组中永远不会超过,但可能存在也可能不存在)。

$dat = 14;  
my @array = (1, 12, 14, 7, 8, 4)

换句话说:

my @new_array = (1, undef, undef, 4, undef, undef, 7, 8, undef, undef, undef, 12, undef, 14);

***编辑**** 更完整的代码sn-p:

foreach $auth (keys %activity) {
my @value = @{ $activity{$auth} };
@value = uniq @value;
@value = sort @value;
s/^0// for @value;

my $count = scalar(grep $_, @value);
my $dat = max( @value );
@{$activity{$auth}} = @value;
}

【问题讨论】:

  • 它是否总是从 1 到 $dat
  • 数组中的值可能会不时不同(但永远不会超过 dat)。我尝试了一些“如果”的变体,但它真的很乱。将值移动到新位置后,我似乎一直无法删除现有的数组索引
  • sort 应该排在uniq 之前
  • @infixed,没办法。最好减少首先排序的元素数量。
  • 我习惯了 shell 命令uniq,它会去除重复的行。如果没有排序,你不会得到重复的行。我想有更灵活的perl 函数,未指定问题中使用的函数。坦白说,我还以为列在perlfunc里,和shell命令差不多,其实不然。

标签: arrays perl splice


【解决方案1】:

简单快速(原文可能出现重复):

my @new_array;
$new_array[$_ - 1] = $_ for @array;

就地(原件中不允许重复):

for (my $i = @array; $i--; ) {
   my $j = $array[$i]-1;
   if ($i < $j) {
      $array[$j] = $j+1;
      $array[$i] = undef;
   }
   elsif ($i > $j) {
      @array[$i, $j] = @array[$j, $i];
      redo;
   }
}

就地(原件中可能出现重复):

for (my $i = @array; $i--; ) {
   my $j = $array[$i]-1;
   if ($i < $j) {
      $array[$j] = $j+1;
      $array[$i] = undef;
   }
   elsif ($i > $j) {
      if ($array[$j] == $j+1) {
         $array[$i] = undef;
      }
      else {
         @array[$i, $j] = @array[$j, $i];
         redo;
      }
   }
}

pop(@array) while @array && !defined($array[-1]);

【讨论】:

  • 从 cmets 看来,用户可能希望就地执行此操作。虽然它会使任务成为某种谜题/高尔夫,而不是有点现实的任务。
  • @Oleg V. Volkov,然后添加@array = @new_array;
  • @Oleg V. Volkov,添加了就地解决方案。
【解决方案2】:

您可以创建一个新数组,其中定义了第一个中的最大值后定义的所有值,然后在这个新数组中取消定义第一个中没有的任何值:

use strict;
use warnings;
use Data::Dumper;


my @array =  ('1', '4', '3');
my $max = (sort { $b <=> $a } @array)[0]; #should be 4

print Dumper(\@array);

my @new_arr;
foreach my $index (0 .. ($max - 1)) {
   $new_arr[$index] = ($index + 1);    
       #Array should be fully populated, @new_arr = ('1', '2', '3', '4');
   $new_arr[$index] = 'undef' unless (grep {$_ eq $new_arr[$index]} @array); 
       #Values not in the original array should be set to undef

}
#  @new_arr should be (''1', 'undef', '3', '4')

print Dumper(\@new_arr); 

输出:

$VAR1 = [
          '1',
          '4',
          '3'
        ];

$VAR1 = [
          1,
          'undef',
          3,
          4
        ];

【讨论】:

  • OP 专门要求提供有效的解决方案,这比之前提交的答案 (O(N)) 效率低得多 (O(N^2))。这是一个糟糕的解决方案。
  • 老实说,我认为您的解决方案看起来也很糟糕,而且很不雅。针对不同使用条件的三个独立实现,带有嵌套的 else/if 循环和 i/j 索引……我的适用于所有条件;删除重复项(如果存在)并完成所需任务。
  • 他给我的绿色检查确实很奇怪......你怎么能说它没有按照他的要求做,我有一个示例代码 sn-p 以及显示的正确输出更多。我知道您的 big-o 符号“更有效”,但是 big-o 并不是衡量效率的唯一标准。我也不和你竞争。我给出了解决他问题的解决方案。根据您的代表,显然这个网站对您来说意义重大,而您无法处理其他人的回答获得绿色检查?
  • 指出我的解决方案适用于您的方案仅适用于这三种方案之一的方案,但对您的事业没有帮助。 // 指出 OP 没有意识到您的解决方案效率低下。 // 如果你有关于我的回答的 cmets,他们应该在那里发布。
  • 我的解决方案适用于所有场景,如果需要,请自行尝试。您的解决方案实际上是三个解决方案。衡量效率的一种方法是简洁。无论如何,我知道根据大 0 表示法,您的解决方案会更快,我从未对此提出异议。你是开始评论我的解决方案的人,当它被你的绿色选中时。事实上,你过去一直是一个很好的资源。知道自己是个混蛋真是太可惜了。
猜你喜欢
  • 2012-01-24
  • 2019-11-03
  • 2021-04-26
  • 2017-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-17
  • 1970-01-01
相关资源
最近更新 更多