在 Perl 中,如何找到数组中最后一个定义的元素?
Posted
技术标签:
【中文标题】在 Perl 中,如何找到数组中最后一个定义的元素?【英文标题】:In Perl, how can I find the last defined element in an array? 【发布时间】:2013-07-27 19:20:12 【问题描述】:使用 Perl,我希望找到数组中定义的最后一个元素。
到目前为止,我有以下内容:
#generating array
$array[100] = (undef);
$array[$columns[1]-1] = $columns [2];
#finding the last element that is defined
for ($i=100; $i>=0; $i--)
if (($array[$i] != undef) && (!defined($lastdef)) )
$lastdef=$i;
我不确定为什么这不起作用。使用 Perl 有什么改进建议吗?
【问题讨论】:
【参考方案1】:以下有点丑陋和晦涩(相比@TLP's excellent answer),但写起来很有趣:
#!/usr/bin/env perl
use strict;
use warnings;
use feature 'say';
for my $i (0, 1)
my $array = generate_array(8, $i);
say join ' ', map $_ // '_', @$array;
say index_of_last_defined_element($array);
sub index_of_last_defined_element
my $x = $# $_[0] ;
my $v = $_[0]->[$x];
return $x if defined($v) or $x < $[;
$# $_[0] -= 1;
goto &index_of_last_defined_element;
sub generate_array
my $size = shift;
my $array = [ (undef) x $size ];
shift or return $array;
$array->[rand $#$array] = 'x';
return $array;
输出:
_ _ _ _ _ _ _ _ -1 _ _ _ _ _ X _ _ 5
当然,这有点傻。你应该使用List::MoreUtils::last_index:
use feature 'say';
use List::MoreUtils qw(last_index);
for my $i (0, 1)
my $array = generate_array(8, $i);
say join ' ', map $_ // '_', @$array;
say last_index defined($_) @$array;
【讨论】:
$[
不是已弃用吗?
是的,$[
已被弃用......但我喜欢偶尔尊重它;-)
很公平,我也不想因为你投下我的票而向你开火。我对使用 last_index
选项犹豫不决,因为它不是核心,但正如您所指出的,它正是它的用途。【参考方案2】:
我不确定为什么这不起作用。使用 Perl 有什么改进建议吗?
你不知道它为什么不起作用的原因是因为你没有使用
use warnings;
如果你有,你会被告知:
Use of uninitialized value in numeric ne (!=) at ...
因为!=
是numeric inequality operator,它会将其参数转换为数字。如果您没有打开warnings
,这将默默地将undef
转换为0
。不用说,开启warnings
是一件非常好的事情,这样你就不会犯这样的错误了。
就是这一行:
if (($array[$i] != undef) ...
应该是这样的
if ((defined($array[$i]) ...
因为是 defined
函数检查值的定义性。这是一个奇怪的错误,因为您甚至在同一行上使用了相同的功能。
另外,您可以通过这样做来简化此操作
if (defined($array[$i]))
$lastdef = $i;
last;
last
将在找到第一个未定义值时结束循环。
您还应该知道,您可以在循环条件上使用非硬编码的最大值:
for (my $i = $#array; $i >= 0; $i--)
$#array
包含数组中现有最高索引的编号。
【讨论】:
感谢您的详细解释。我使用 use warnings; 但也使用 no warnings qw(uninitialized); 以避免打印“在@intronAbundance 中使用未初始化的值在串联 (.) 或字符串中”,因为我知道有些值是未定义的。 .我应该在修复脚本时删除它。我也试过 defined($array[$i]) - 我的错误是忘记结束循环。再次感谢您花时间逐行解释。 很少需要关闭警告,而且总是一个坏主意。 可选,for
循环可以是:for my $i ( reverse 0 .. $#array )
@shawnhcorey 如果数组的大小是1_000_000
怎么办?
数组本身是否适合内存?【参考方案3】:
使用List::Util 函数可以更简洁。这将找到定义的数组中的最后一个元素,但不是它的索引。要查找它的索引,您可以使用defined
而不是eq
执行类似于this 的回答。
use List::Util qw(first);
my $lastdef = first defined($_) reverse @array;
【讨论】:
您应该使用List::MoreUtils::last_index,而不是通过反转@array
来使内存需求加倍。
@SinanÜnür 这不是核心,所以我不想假设用户会去 CPAN。没有理由对意见的有效答案投反对票。【参考方案4】:
您需要从 99 开始,因为 100 个元素数组的索引为:0 .. 99。一旦找到该元素就中断循环:
#!/usr/bin/perl
use strict;
use warnings;
my @array = (1, 2, undef);
my $lastdef;
for (my $i = $#array; $i>=0; $i--)
if (defined($array[$i]))
$lastdef=$i;
last;
print $lastdef;
打印:1
【讨论】:
使用List::MoreUtils::last_index。 @SinanÜnür 是的,这是我的一个通用函数。它们允许使用任何条件,而不是defined()
条件。
除非你用List::MoreUtils::last_index
获得C性能见cpansearch.perl.org/src/ADAMK/List-MoreUtils-0.33/MoreUtils.xs
@SinanÜnür 是的,看到它。以上是关于在 Perl 中,如何找到数组中最后一个定义的元素?的主要内容,如果未能解决你的问题,请参考以下文章
perl :在数组@array中增加新的元素有几种方法?请详细一一列出,谢谢!