Как перебрать поддиапазоны в "циклическом массиве"? - PullRequest
1 голос
/ 31 августа 2010

Я пытаюсь написать следующую подпрограмму perl. Даны массив a длины n, индекс i в массиве (0<=i<n длина окна восходящего потока u и длина окна нисходящего потока d.

Я хочу перебрать значения в верхнем и нижнем окнах до i. В простейшем случае это будет повторять значения в a[i-u..i-1] (верхнее окно) и a[i+1..i+d] (нижнее окно).

Например: если мой массив 1 2 3 4 5 6 7 8 9 10, i=5 и оба размера окна 2, значения в восходящем направлении просто 6 7, а значения в нисходящем направлении 9 10.

Однако есть два осложнения:

  1. Я хотел бы считать, что мой массив циклический. Если i относительно мало (близко к 0) или большой (близко к n), затем один окна могут не вписываться в массив. В таком случае я хочу посмотреть в массиве как циклический. за Например, если мой массив 1 2 3 4 5 6 7 8 9 10, i=8 и оба размера окна 4, значения в восходящем направлении просто 4 5 6 7 но вниз по течению значения 9 10 1 2.

  2. Я бы предпочел итерацию над этими значениями без явного копируя их в новый массив, так как они могут быть очень длинными.

1 Ответ

6 голосов
/ 31 августа 2010

Вы можете просто получить список признаков, используя оператор диапазона (..), вычитая верхнее окно из $i и добавляя нижнее окно к $i.Вам нужно будет не пропускать итератор, когда итератор равен $i, если вы не хотите, чтобы $i th значение.

Вам нужно будет использовать оператор по модулю (%)держать индекс в границах массива.Учитывая массив размером 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), это должно быть безопасноиспользуйте integer прагму.

...