В Perl как проверить, соответствует ли массив значению, указанному хотя бы один раз в его содержимом? - PullRequest
1 голос
/ 15 сентября 2011

Я никогда прежде не работал с Perl (избегал, где мог), и поэтому мои знания разбросаны по теме.

Я знаю, что скрипт, на который я смотрю, имеет массив значений ProductID в@ :: s_Ship_sShipProducts.

Я пытался проверить, начинался ли какой-либо из ProductID в массиве с B или S, и, если это так, выполнял функцию, иначе выполняю другую функцию.Но в итоге я сделал для каждого ProductID заявление.Это то, что у меня (по общему признанию) было.

my $i;
for $i (0 .. $#::s_Ship_sShipProducts) # for each product
    if  ($::s_Ship_sShipProducts[$i] =~ /^(B|S)/) # Determine if B or S product
        {
        if (defined $phashBandDefinition->{'FreeOver'} && CalculatePrice() > 250)
        {$nCost = 0;}
        }
    else    {
        if (defined $phashBandDefinition->{'FreeOver'} && CalculatePrice() > $phashBandDefinition->{'FreeOver'})
        {$nCost = 0;}
        }

Как я мог изменить это так, чтобы массив проверялся, чтобы видеть, был ли какой-либо ProductID верным и возвращать true, или false, если ничего не соответствовало?Затем выполнить соответствующую функцию, основанную на true или false?Я немного почитал, но все еще в темноте.Спасибо за ваше время.

Ответы [ 2 ]

6 голосов
/ 15 сентября 2011

Если массив не слишком велик (или вас не очень заботит ЭТО по поводу производительности), вы можете проверить, есть ли какие-либо совпадающие значения с помощью grep:

if (my @matching_elements = grep { /^(B|S)/ } @::s_Ship_sShipProducts) {
   # Better yet use /^[BS]/ expression - more idiomatic/readable
   print "Found B/S\n";
} else {
   print "NOT Found B/S\n";
}

Когда закончите, @matching_elements будет содержать список совпадающих идентификаторов.

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


Кстати, ваш подход к поиску работает отлично, вам просто нужно один раз выйти из циклавы нашли - и для загрузки - это один из оптимизированных подходов, показанных в списке выше:

for my $i (0 .. $#::s_Ship_sShipProducts) # for each product
    if  ($::s_Ship_sShipProducts[$i] =~ /^[BS]/) {  # Determine if B or S product
        # Execute your logic here
        last; # Found, get out of the loop.
    } 
}

ПРИМЕЧАНИЕ. В Perl 5.10 и выше вы можете - вместо grep - использоватьтак называемый оператор «умного матча» ~~:

if (@::s_Ship_sShipProducts ~~ /^(B|S)/) {
    # Your logic
}
2 голосов
/ 15 сентября 2011

Я не совсем уверен, что слежу за вашим вопросом, но думаю, что вы ищете grep .

my @matched_products = grep(/^(B|S)/,@::s_Ship_sShipProducts);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...