我正在尝试编写以下 Perl 子例程。给定一个长度为 n
的数组 a
,数组中的索引 i
(0<=i上游窗口长度 u
和下游窗口长度 d
我想将上游窗口和下游窗口中的值迭代到 i
。在最简单的情况下,这将迭代 a[iu..i-1]
(上游窗口)和 a[i+1..i+d]
中的值。 code> (下游窗口)。
例如:如果我的数组是 1 2 3 4 5 6 7 8 9 10
,i=5
并且两个窗口大小都是 2
,上游值只是6 7
,下游值是9 10
但是,有两个复杂的情况:
-
我想考虑 。我的数组是循环的。如果 i
相对较小(接近
0)或大(接近n
),然后是1
窗户可能不适合
大批。在这种情况下,我想看看
将数组视为循环数组。为了
例如,如果我的数组是 1 2 3 4 5 6 7 8 9 10
、i=8
以及两个窗口大小
是 4
,上游值为
只是4 5 6 7
,但是下游
值为9 10 1 2
。
-
我更喜欢某种迭代方式
在没有明确说明的情况下超过这些值
将它们复制到一个新数组中,因为
它们可能很长。
I'm trying to write the following Perl subroutine. Given are an array a
of length n
, an index i
in the array (0<=i<n
an upstream window length u
and a downstream window length d
.
I want to iterate over the values in the upstream window and the downstream window to i
. In the simplest case, this will iterating over the values in a[i-u..i-1]
(upstream window) and a[i+1..i+d]
(downstream window).
For example: if my array is 1 2 3 4 5 6 7 8 9 10
, i=5
and both window sizes are 2
, the upstream values are simply 6 7
and the downstream values are 9 10
.
However, there are two complications:
-
I would like to consider my array is cyclic. If i
is relatively small (close to
0) or large (close to n
), then one
of the windows may not fit in the
array. In that case, I want to look
at the array as a cyclic one. for
example, if my array is 1 2 3 4 5 6 7 8 9 10
, i=8
and both window sizes
are 4
, the upstream values are
simply 4 5 6 7
, but the downstream
values are 9 10 1 2
.
-
I would prefer some way to iterate
over these values without explicitly
copying them into a new array, since
they might be very long.
发布评论
评论(1)
您可以使用范围运算符 (
..
) 获取索引列表,方法是从$i
中减去上游窗口并将下游窗口添加到$i< /代码>。如果您不想要第
$i
个值,则需要记住当迭代器等于$i
时跳过迭代器。您将需要使用模运算符 (
%
) 将索引保持在数组的范围内。给定一个大小为11
的数组,我们可以看到,通过使用11
修改索引,它将始终指向数组中的正确位置:您可能会遇到巨大的问题数字(即大于您的平台在无符号整数中保存的数字),因为 Perl 5 更改了模数使用的算法。它变得更像 C 的
fmod
(但也有一些区别)。您可能还不想使用
integer
编译指示。它使%
更快,但您得到了 C 模运算符的行为。 ANSI 和 ISO 都没有定义 C 应该如何处理负数,因此您可能会也可能不会得到有效的索引。当然,只要C版本回吐或者
应该没问题(如果不是很便携的话)。
看起来 C99 定义了模运算符来返回第二种情况,只要
perl
编译为C99 编译器(带有 C99 标志)应该可以安全地使用整数
编译指示。You can just get a list of indices using the range operator (
..
) by subtracting the upstream window from$i
and adding the downstream window to$i
. You will need to remember to skip the iterator when the iterator is equal to$i
if you don't want that$i
th value.You will need to use the modulo operator (
%
) to keep the index within the bounds of the array. Given an array of size11
, we can see that by modifying the index with11
it will always point to the right place in the array:You may run into problems with huge numbers (i.e., numbers larger than what your platform holds in an unsigned integer), because Perl 5 changes the algorithm the modulus uses around there. It becomes more like C's
fmod
(but there are some differences).You may also want to not use the
integer
pragma. It makes%
faster, but you get the behavior of the C modulo operator. Neither ANSI nor ISO define what C should do with negative numbers, so you may or may not get a valid index back. Of course, so long as the version of C spits back eitheror
it should be fine (if not very portable).
It looks like C99 defines the modulo operator to return the second case, so long as
perl
gets compiled with a C99 compiler (with the C99 flag on) it should be safe to use theinteger
pragma.