Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 首先迭代perl数组中最多n个元素_Arrays_Perl_Loops - Fatal编程技术网

Arrays 首先迭代perl数组中最多n个元素

Arrays 首先迭代perl数组中最多n个元素,arrays,perl,loops,Arrays,Perl,Loops,最令人愉快的惯用写作方式是什么 for (take(100,@array)) {...} 假设没有take(它获取列表的前n个元素,但如果没有n个元素则更少) 我考虑的事情: for(@array[0..99]){…} 但如果@array的元素少于100个,则该操作将失败 for(@array[0..min(99,$#array)]{…} 但是min不是Perl中的标准函数 for(splice@array,0100){…} 这会改变数组 您可以在循环内部添加额外的检查,以在到达终点后中断

最令人愉快的惯用写作方式是什么

for (take(100,@array)) {...}
假设没有
take
(它获取列表的前n个元素,但如果没有n个元素则更少)

我考虑的事情:

  • for(@array[0..99]){…}

    但如果
    @array
    的元素少于100个,则该操作将失败

  • for(@array[0..min(99,$#array)]{…}

    但是
    min
    不是Perl中的标准函数

  • for(splice@array,0100){…}

    这会改变数组


您可以在循环内部添加额外的检查,以在到达终点后中断

my @arr = (1 .. 90);

for ( @arr[0..99]) {
    last unless defined $_;
    say;
}
但对于介于
unde
值之间的数组,这不起作用,例如:

my @foo = (1, 2, undef, 4);
my @bar;
$bar[2] = 'foo'; # (undef, undef, 'foo')
for(@array[0..min(99,$#array)]{…}

但是min不是Perl中的标准函数

是模块中的标准功能,从5.7.3开始,它是核心的一部分

use List::Util qw(min);

for (@array[0..min(99,$#array)]) {  # generator in 5.8.8+
  ...
}

请注意,Perl5.8.8以后的版本,或者更早的版本,足够聪明,可以将该表达式理解为生成器而不是切片。也就是说,从@array一次提取一个元素0到$terminus,而不是提取和复制一个匿名切片。

您已经指出,您发现以下内容最干净:

take(100, @array)

所以要回答你的问题,什么是最干净的,那就是!我不明白你为什么要寻找替代方案。

使用
map
怎么样:

my @array = qw ( 1 2 3 4 );
print join "\n", map { $_ // () } @array[0..10]; 
这将从列表中获取10个元素,但对其应用“已定义”测试-如果未定义,则返回空列表

所以你可以:

for ( map { $_ // () } @array[0..100] ) { 
   #do something
}
注意-
/
是一个定义的or运算符,仅在perl 5.10+中可用。您可以使用定义的三元:

print join "\n", map { defined ? $_ : () } @array[0..10]; 
你想要CPAN模块吗


其他的回答已经涵盖了这一点,但是,为了彻底起见,有几个“南瓜perl”
gather/take
在CPAN上的实现:-)

还有Damian Conway的,几乎相同,但需要
Perl6::Export

它们让你以你想要的方式处理列表。e、 g.要“
”字母表的一半:

 perl -E 'use List::Gather; @lpha = ("a" .. "z"); 
         @half = gather { for (@lpha){ take $_ if gathered < 13 } } ; say @half'
 abcdefghijklm
gather{}
块中执行此操作(也可以使用
List::gather
):

输出:

[
    [0] "a",
    [1] "b",
    [2] "c",
    [3] "d",
    [4] "e",
    [5] "f",
    [6] "g",
    [7] "x",
    [8] "z"
]

我认为应该使用迭代器模式,即

my $iterator = create_iterator(100);
while (my $element = $iterator->()) {
   ...;
}
limit
可能嵌入到迭代器创建中,即

sub create_iterator {
     my $limit = shift;
     my @data = (0 x 1000);
     my $i = 0;
     return sub {
        return $data[$i++] if ($i < @data);
     }
}
sub-create\u迭代器{
我的$limit=shift;
my@data=(0 x 1000);
我的$i=0;
返回接头{
如果($i<@data),则返回$data[$i++]if;
}
}


PS.有一个限制,
unde
不能成为
@data

的一部分
take
做什么?会做你想做的吗?不是真的;我正在寻找获取元素的方法。不仅仅是
undef
。。。任何计算结果为false(
0
”)的内容,等等@zaid当然是。请随意编辑,我在打电话。“但这对介于未定义值之间的数组不起作用,比如这些”–这对我来说是一个阻碍,因为它看起来非常不可靠。@JoachimBreitner如果你不想在子例程中添加大量检查,你可以使用CPAN模块来完成该部分。是否合适?请参阅我的
gather/take
响应的结尾,以获取一个示例。换句话说,编写一个子例程。问题与@simbabque的解决方案相同:如果没有定义所有元素,则会中断。可能是一种极端情况,但我不认为代码不可靠的原因。我认为在这里也会起作用:-D
perl-Mboolean-E'@array=(“a”。.g',”,unde,unde,“x”,“0”,“z”);打印联接“\n”,映射{boolean($\u)?$\u:()}@array[0..100];'授权-它会根据其所做的操作过滤
undef
。我不认为这是一个很大的问题,因为我很少有在循环上下文中操作的present-but-
undf
;我希望有更优雅的东西,但我想这是最好的解决方案。你知道哪里有文件证明这不会生成临时列表吗?我知道,尽管这方面的文档也很简洁。@ThisSuitesBlack不,不,我不知道。我使用了一个
tie()
d数组,该数组在每次抓取时都会发出吠声,以说服自己该优化已经到位。(每个循环一次连续抓取,而不是一次全部抓取。)方法不错!没想到。
head
听起来像是一个基本的“实用程序”。。。对于列表;-)嗯,比起像
gather/take
@G.Cito-yup这样的时髦东西,更“基本的实用程序”。请看是的,我希望这样的东西在语言本身中很容易表达,或者至少在默认情况下可以提供。唯一的缺点是,在
for
循环中,此函数将n个元素复制到一个匿名数组中,然后进行迭代。相比之下,
for
循环中的显式常规切片在每次迭代中逐个获取元素。除非n变大,否则这无关紧要。如果
unde
在列表中,这与另一个答案的缺点是相同的。
perl -E 'use Syntax::Keyword::Gather; @lpha = ("a".."g"); 
        @half = gather { for (@lpha){ take if gathered < 13 } }; say @half'
perl -E 'use boolean; use List::Gather; 
        @lpha = ("a" .. "g", "", undef, undef, "x", "0", "z"); 
        @half = gather { for (@lpha){ take $_ if boolean($_) && gathered < 13 }};
        use DDP; p @half;'
[
    [0] "a",
    [1] "b",
    [2] "c",
    [3] "d",
    [4] "e",
    [5] "f",
    [6] "g",
    [7] "x",
    [8] "z"
]
my $iterator = create_iterator(100);
while (my $element = $iterator->()) {
   ...;
}
sub create_iterator {
     my $limit = shift;
     my @data = (0 x 1000);
     my $i = 0;
     return sub {
        return $data[$i++] if ($i < @data);
     }
}