2015-04-29 2 views
-1

У меня есть массив с двумя значениями и необходимо выполнить некоторые операции, если вход не находится в этом массиве.Проверить конкретное значение не в массиве

Я попытался как

if ($a ne ('value1' || 'value2') 

if (($a ne 'value1') || ($a ne 'value2')) 

Оба метода не работают. Кто-нибудь может помочь?

+3

Вы упомянули массив. Я не вижу массив в вашем коде. Если вы действительно работаете с массивом, это может помочь: http://stackoverflow.com/questions/2860226/how-can-i-check-if-a-perl-array-contains-a-particular-value – bloodyKnuckles

ответ

5

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

if ($x ne 'value1' and $x ne 'value2') { 

Для реального массива любого размера:

if (not grep $_ eq $x, @array) { 

(я использую $x вместо $a как $a особенный - см perlvar.)

+2

резерв и для управления потоком; use && в выражениях – ysth

+1

Вам следует избегать использования 'grep' для этого: https://metacpan.org/pod/release/THALJEF/Perl-Critic-1.125/lib/Perl/Critic/Policy/BuiltinFunctions/ProhibitBooleanGrep.pm –

+1

@ VadimPushtaev Это, безусловно, справедливо, если вы проверяете, есть ли что-то * в массиве *, но в этом случае мы проверяем, есть ли что-то * не * в массиве, что обязательно требует итерации через каждый отдельный элемент. Вы можете использовать 'grep' или' List :: MoreUtils :: none', забрать свой яд. – ThisSuitIsBlackNot

4
if ($a ne ('value1' || 'value2') 

вычисляет

if ($a ne 'value1') 

и

if (($a ne 'value1') || ($a ne 'value2')) 

всегда TRUE.

Вы можете попробовать

if ($a ne 'value1' and $a ne 'value2') 

или

if (!grep{$a eq $_} 'value1', 'value2') 
+0

Вам следует избегать использования 'grep' для этого: https://metacpan.org/pod/release/THALJEF/Perl-Critic-1.125/lib/Perl/Critic/Policy/BuiltinFunctions/ProhibitBooleanGrep.pm –

+1

@VadimPushtaev: Я думаю * следует избегать * завышает его. Это просто один из указаний * Perl Best Practices *, и причина в том, что 'grep' сравнивает * все * элементы списка, независимо от того, может ли более раннее совпадение сократить процесс. До тех пор, пока это имеет в виду, 'grep' - прекрасный способ сделать это, тем более, что список состоит всего из двух элементов, а дополнительные вычисления будут незначительными в любом коде, который также считывает данные из файла на диске – Borodin

-1

Ваша переменная $a не оценивается как индекс в array без [INDEX], но рассматривалась как скаляр.

Два значения array:

$array[0] = "X"; $array[1] = "Y";

или

@array = qw/X Y/;

Проверка состояния с использованием if:

if ($array[0] ne "Your-String" || $array[1] ne "Your-String")

+0

Я думаю, что способ, которым представлен пример кода, предполагает, что '@ array' находится где-то, с чем сопоставляется значение' $ a'. Это не самый яркий примерный код, но OP должен быть тем, кто его изменит. –

0

Вы также можете использовать смарт-оператор матча:

не

если ($ х ~~ [ 'значению1', 'value2'])

+0

Я пропустил «' ~~ '», если/когда он уйдет. Всегда есть ['match :: simple'] (https://metacpan.org/pod/match::simple) @tobyink. –

+2

Просто для того, чтобы прояснить комментарий @ G.Cito по отношению к smartmatch уйти ... smartmatch был [отмечен экспериментальным в 5.18.0] (http://perldoc.perl.org/perl5180delta.html#The-smartmatch-family -of-features-are-now-experimental): «Понятно, что smartmatch почти наверняка либо изменится, либо уйдет в будущем. Опираясь на его текущее поведение, не рекомендуется». – ThisSuitIsBlackNot

+0

@ThisSuitIsBlackNot Спасибо, я попытался уточнить это немного больше в моем ответе. Направляя p5p perlmonks и @ikegami @leont, похоже, мы можем надеяться на гораздо более простую версию '~~' в будущих версиях Perl - поведение которых может быть расширено и расширено с помощью модуля утилиты и экосистемы CPAN./me пересекает пальцы –

1

Опираясь на smartmatch раствора @Dilbertino (хороший ник) с помощью match::simple по @tobyink, чтобы облегчить боль smartmatch уезжает (я пропускаю это уже):

use match::simple; 
my @array = qw(abcd.txt abcdeff.txt abcdweff.txt abcdefrgt.txt); 
my $x="abcd.txt" ; 
say "it's there" if ($x |M| \@array); 

|M| оператор из match::simple может быть заменен match функцией, немного ускоряется (реализовано с помощью XS):

use match::simple qw(match); 
my @array = qw(abcd.txt abcdeff.txt abcdweff.txt abcdefrgt.txt); 
my $x="xyz.txt" ; 

if (match ($x, \@array)) { 
    say "it's there!" ; 
} 
else { 
    say "no hay nada"; 
} 

Это «просто», потому что RHS контролирует поведение. С match::simple, если вы соответствуете массиву на RHS, он должен быть arrayref.

Smart::Match также имеет функцию none. Для того, чтобы использовать его, вы должны сделать следующее:

if ($x ~~ none (@array)) { 
    say "not here so do stuff ..."; 
} 

Приложение

Обсуждение здесь на Stackoverlfow (см: Perl 5.20 and the fate of smart matching and given-when?) и в других местах (срPerlmonks article по @ikegami от около жемчужно-5.18) дает контекст для эксперимента smartmatch. TLDR; вещи могут измениться в будущем, но между тем, вы можете пойти назад во времени и use match::smart qw(match); с perl-5.8.9 доказать еще раз, что perl никогда не умирает; он просто возвращается к своей экосистеме.

В будущем что-то вроде Smart::Match (т.е.. Модуль CPAN непрофильного не понятие) может помочь перегружать упрощенный смарт-оператор согласования с вспомогательными функциями, которые считывают как наречия и прилагательных и имеют дополнительный бонус (как я понять) прояснения/упрощения вещей для самого perl, поскольку оператор ~~ будет иметь менее двусмысленный контекст для своих операций.

+1

Тема не появилась снова на p5p с тех постов моих. Кто-то заинтересован в повышении – ikegami

6

Вы можете использовать функцию none от List::MoreUtils.

Если у вас действительно есть массив как ваша подчиненная линия говорит, то ваш код будет выглядеть следующим образом

use List::MoreUtils 'none'; 

if (none { $_ eq $a } @array) { 
    # Do stuff 
} 

или если у вас действительно есть две константы, то вы могли бы использовать этот

if (none { $_ eq $a } 'value1', 'value2') { 
    # Do stuff 
} 

, но в в этом случае я бы предпочел посмотреть только

if ($a ne 'value1' and $a ne 'value2') { 
    # Do stuff 
} 
+0

++ Я никогда не думал об этом, но ['Smart :: Match'] (https://metacpan.org/pod/Smart::Match) работает как модуль« Util ». Он также имеет функцию 'none', в которой вы бы сделали:' if ($ x ~~ none (@array)) {say "не здесь так делать вещи"} '. Это почти так, как если бы он действовал как усовершенствование 'Match :: Util' для будущей (очень упрощенной) версии' ~~ 'оператора. Добавление «Smart :: Match» в качестве ответа. –

+2

@ G.Cito: Мне нравится давать умное соответствие или что-то связанное с ним, очень широкое место, и я боюсь писать любое количество кода, используя версию Perl 6.Проблема в том, что он пытается быть оператором * DWIM *, и невозможно запомнить, что он делает с любой заданной комбинацией параметров. Я бы очень скоро сказал, что я имею в виду и получаю правильный результат, а также понимаю, что другие понимают мой код. – Borodin

+0

Я вижу, как это может быть настолько «умным», что его будет трудно упростить. Упрощение чего-то может быть сложным, но для его исправления требуется много времени. –

0

Я бы сделал что-то подобное с помощью grep с regex матч

#!/usr/bin/perl 
use warnings; 
use strict; 

my @array = ('value1','value2'); 

if(grep(/\bvalue1\b|\bvalue2\b/, @array)){ 
    print "Not Found\n"; 
} 
else { 
    print "do something\n"; 
} 
+0

Вам следует избегать использования 'grep' для этого: https://metacpan.org/pod/release/THALJEF/Perl- критик-1,125/Библиотека/Perl/критик/Политика/BuiltinFunctions/ProhibitBooleanGrep.pm –

Смежные вопросы