Можно ли инициализировать массив с заданным размером в Perl?

У меня есть раздел в моем коде, где я знаю, что мне понадобится массив, и я точно знаю, сколько элементов потребуется массиву. Этот раздел кода будет повторяться много, поэтому я мог бы получить очень большую экономию времени, сначала инициализировав этот массив до размера, который, как я знаю, вам понадобится, а затем заполнить его или просто нажимать на него (нажатие будет O ( n) в отличие от заполнения уже созданных пространств, которые были бы O (1)).

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

my @array; $array[49] =0;

чтобы получить массив 50 элементов, но это выглядит очень уродливо для меня, и я чувствую, что должен быть лучший способ. Идеи?

Ответы

Ответ 1

Честно говоря, ваш путь совершенно прекрасен, так как явное изменение размера массива: $#array = 49;;

Ответ 2

  • Первое правило Optimization Club - это не оптимизация.
  • Второе правило Клуба Оптимизации - это вы делаете не оптимизировать без измерения.

Измерьте, измерьте, измерьте перед тем, как идти, и предположите, что вы можете сделать это быстрее, обманув Perl. Perl делал оптимизацию общего использования намного дольше, чем у вас. Доверяйте этому.

Ответ 3

Всякий раз, когда вы думаете об этом типе оптимизации, выполните некоторые профилирования! Результат может быть не таким, как вы ожидаете. Например, я использовал следующий быстрый script, чтобы проверить вашу теорию, что предварительное выделение массива происходит быстрее:

for ( my $loops = 0; $loops < 100000; $loops++ )
{
    my @arr;

    for ( my $foo = 0; $foo < 50; $foo++ ) {
        push @arr, 'bar';
    }
}

Это заняло 2,13 секунды.

for ( my $loops = 0; $loops < 100000; $loops++ )
{
    my @arr;
    $arr[49] = 0;

    for ( my $foo = 0; $foo < 50; $foo++ ) {
        $arr[$foo] = 'bar';
    }
}

Это заняло 2,16 секунды (я провел несколько тестов несколько раз). Таким образом, на самом деле это заканчивается тем, что быстрее разрешить дескриптор perl выделять массив по мере необходимости.

Обновление

После внесения изменений, предложенных ysth, цифры имеют немного больше смысла: 2.27 секунд для метода "push" и 2.21 для предварительного выделения. Тем не менее, я бы поставил под сомнение, действительно ли такая оптимизация будет экономить в любое время (разница составляла всего 0,06 секунды после 100 000 итераций).

Ответ 4

Твой путь отличный, и это тоже DVK. Способ сделать это в одной команде может быть:

@array = (0.. 49);

Но я не уверен, что он более изящный, так как он присваивает каждому элементу значение от 1 до 49, но, вероятно, более интуитивно понятно для программиста, не сильно влияющего на синтаксис Perl.

Ответ 5

Вместо определенного значения используйте undef

my @array;
$array[49] = undef;

Ответ 6

Предварительное выделение может не сильно помочь скорости, но может помочь вернуть память в систему, если выделенные фрагменты достаточно велики