Есть ли менее неуклюжая альтернатива для копирования элементов "n"?

В мире многих @choices
С помощью $limit, что можно сделать,
Жизнь предлагает много @options
Но время от времени один или два.
Чтобы минимизировать линейный шум
Что может Тим Тоуди сделать?

Вот несколько способов, о которых я думал, но они кажутся такими неуклюжими. Конечно, там есть более элегантный способ DWIM:

  • Подробный однострочный

    my @choices = @options <= $limit ? @options : @options[0..$limit-1];  # Blech
    
  • Управление срезами

    my @choices = @options[0..(@options <= $limit ? $#options : $limit - 1)]; # Even worse
    
  • Сырный ломтик внутри среза

    my @choices = @options[0..($#options, $limit-1 )[@options > $limit]];  # Crazy eyes
    
  • Более четкое намерение, но более двух строк

    my @choices = @options;
       @choices = @options[0..$limit-1] if $limit < @options;
    

Ответ 1

@choices = @options; splice @choices, $limit;  # "splice() offset past end" before v5.16

Это также можно сделать в одном выражении!

@choices = splice @{[@options]}, 0, $limit;

А также

splice @{$choices_ref=[@options]}, $limit;  # Warns "splice() offset past end" before v5.16
splice $choices_ref=[@options], $limit;     # Ditto. Requires Perl v5.14. "Experimental"

Ответ 2

my @choices = @options[0..min($#options, $limit-1)];

Короткий, простой, понятный.

Ответ 3

Из предоставленных вами опций мне действительно нравятся # 1 и # 4, и у них есть определенные письменные заявления, подобные тем, которые были раньше. Если бы эти параметры меня действительно беспокоили, я мог бы написать так:

use strict;
use warnings;

use List::Util qw(min);
use Data::Dumper;

my @options = ('a'..'c');
my $limit   = 5;

my @choices = @options[0..min($limit-1, $#options)];
print Dumper \@choices;
# $VAR1 = [
#      'a',
#      'b',
#      'c'
#    ];    

$limit = 2;
@choices = @options[0..min($limit-1, $#options)];
print Dumper \@choices;
# $VAR1 = [
#       'a',
#       'b'
#   ];

но это во многом основано на мнениях, и я уверен, что другие люди сделают это по-другому.

Ответ 4

Я бы использовал splice:

my @choices = splice ( @options, 0, $limit ); 

Обратите внимание, что splice действует как shift/pop и изменяет исходный массив - если это нежелательно, то сначала скопируйте его.

Ответ 5

my @choices = first_x_ele($limit, @options);

Если вы думаете, что что-то неясно, используйте суб! Как вы реализуете sub, это не очень важно, но короткий:

sub first_x_ele { my $x = shift; splice(@_, 0, $x) }