如何迭代“循环数组”中的子范围?

发布于 2024-09-16 20:33:23 字数 818 浏览 10 评论 0 原文

我正在尝试编写以下 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 10i=5 并且两个窗口大小都是 2,上游值只是6 7,下游值是9 10

但是,有两个复杂的情况:

  1. 我想考虑 。我的数组是循环的。如果 i 相对较小(接近 0)或大(接近n),然后是1 窗户可能不适合 大批。在这种情况下,我想看看 将数组视为循环数组。为了 例如,如果我的数组是 1 2 3 4 5 6 7 8 9 10i=8 以及两个窗口大小 是 4,上游值为 只是4 5 6 7,但是下游 值为9 10 1 2

  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:

  1. 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.

  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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

吃颗糖壮壮胆 2024-09-23 20:33:23

您可以使用范围运算符 (..) 获取索引列表,方法是从 $i 中减去上游窗口并将下游窗口添加到 $i< /代码>。如果您不想要第 $i 个值,则需要记住当迭代器等于 $i 时跳过迭代器。

您将需要使用模运算符 (%) 将索引保持在数组的范围内。给定一个大小为 11 的数组,我们可以看到,通过使用 11 修改索引,它将始终指向数组中的正确位置:

#!/usr/bin/perl

use strict;
use warnings;

for my $i (-22 .. 22) {
    print "$i => ", $i % 11, "\n";
}

您可能会遇到巨大的问题数字(即大于您的平台在无符号整数中保存的数字),因为 Perl 5 更改了模数使用的算法。它变得更像 C 的 fmod (但也有一些区别)。

您可能还不想使用 integer 编译指示。它使 % 更快,但您得到了 C 模运算符的行为。 ANSI 和 ISO 都没有定义 C 应该如何处理负数,因此您可能会也可能不会得到有效的索引。当然,只要C版本回吐

X   -5 -4 -3 -2 -1 0 1
X%5  0 -4 -3 -2 -1 0 1

或者

X   -5 -4 -3 -2 -1 0 1
X%5  0  1  2  3  4 0 1

应该没问题(如果不是很便携的话)。

看起来 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 $ith value.

You will need to use the modulo operator (%) to keep the index within the bounds of the array. Given an array of size 11, we can see that by modifying the index with 11 it will always point to the right place in the array:

#!/usr/bin/perl

use strict;
use warnings;

for my $i (-22 .. 22) {
    print "$i => ", $i % 11, "\n";
}

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 either

X   -5 -4 -3 -2 -1 0 1
X%5  0 -4 -3 -2 -1 0 1

or

X   -5 -4 -3 -2 -1 0 1
X%5  0  1  2  3  4 0 1

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 the integer pragma.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文