在 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中增加新的元素有几种方法?请详细一一列出,谢谢!

在 Perl 中计算稀疏数组中的元素

Perl删除数组中元素的多种方法

perl数组的长度与元素个数

如何在 Mongoose 中找到与数组字段的最后一个元素与给定查询值匹配的所有文档?

java中 如何在一个数组中删除里面的元素