Что такое сокращенный способ проверки того, что несколько переменных ВСЕ равны одному значению в выражении IF? (PHP)

Есть ли сокращенный способ написания кода ниже?

if (($tstat=='no_prices')&&($l1stat=='no_prices')&&($l2stat=='no_prices')&&($l3stat=='no_prices'))
{                                   
    //do something
}

Я попытался использовать приведенный ниже код, но он сделал что-то, когда одна из переменных не была равна "no_prices".

if (($tstat && $l1stat && $l2stat && $l3stat)=='no_prices')
{
    //do something
}

Чтобы проверить, что строки не вызывают проблем, я попытался заменить 0 на "no_prices" и 1 на другие значения, но результат был одинаков.

Ответы

Ответ 1

array_flip в несколько раз быстрее array_unique:

function all_equal($arr, $value) {
  return array_keys(array_flip($arr)) == array($value);
}

$arr = array($tstat, $l1stat, $l2stat, $l3stat);

echo all_equal($arr, 'no_prices');

Быстрый профиль для ответов, предоставленных до сих пор, для 1000 итераций по длине массива 1000:

  array_flip: 0.07321620 seconds
array_unique: 0.32569408 seconds
     foreach: 0.15136194 seconds
array_filter: 0.41404295 seconds

Код, используемый для профиля, находится здесь: http://codepad.org/szgNfWHe

Примечание. Поскольку @cypherabe справедливо указывает на, array_flip не обгоняет array_unique, пока массив не будет иметь как минимум 5 элементов, и не обгоняет foreach, пока массив не будет содержать как минимум 10 элементов.

Ответ 2

Если я не ошибаюсь, там нет собственного способа сделать это. Если это то, что вам нужно часто проверять, попробуйте использовать для него настраиваемую функцию, например:

function allEquals($chkstr, $vals) {
    if (!is_array($vals)) { die('allEquals() $vals not an array'); }
    foreach ($vals AS $v) {
        if ($chkstr != $v) { return false; }
    }
    return true;
}

Ответ 3

Моя первая идея войдет в API PHP Array:

// $tstadt, $l1stat, … are all "no_prices"
$isAllNoPrice = array_unique(array($tstat, $l1stat, …)) == array("no_prices"));
if ($isAllNoPrice) {
    // …

}

Документация обязательна, иначе никто (включая себя) не поймет код.

Если эффективность может быть проблемой, другие указали, что array_unique() кажется медленным. Использование ключей хэш-таблицы будет следующим подходом:

// $tstadt, $l1stat, … are all "no_prices"
$varsMap = array(
    $tstat  => null,
    $l1stat => null,
    // …
);
if (array_keys($varsMap) == array("no_prices")) {
    // …

}

Но теперь стена кода растет. PHP предлагает один оператор, который почти делает то, что вы хотите, и его можно связать: &

$v1 = "no_prices";
$v2 = "no_prices";
$v3 = "no_prices";

var_dump(($v1 & $v2 & $v3) == "no_prices"); // bool(true)

$v3 = "prices";
var_dump(($v1 & $v2 & $v3) == "no_prices"); // bool(false)

Я сказал, что он почти делает то, что вы хотите: Есть случаи, когда вы будете иметь ложные срабатывания:

$v1 = 1;
$v2 = 1;
$v3 = 3;

var_dump(($v1 & $v2 & $v3) == 1); // bool(true)

Для строк, кажется, вырезается битовая маска для кратчайшей строки:

$v1 = "abcd";
$v2 = "ab";
$v3 = "abc";

var_dump($v1 & $v2 & $v3); // "ab"
var_dump(($v1 & $v2 & $v3) == "ab"); // bool(true)

Поэтому я не рекомендую это как решение общего назначения. Только если вы знаете (= unit testing), что ваши значения находятся в наборе, где никакая комбинация никогда не приводит к ложному положительному (например, { "собака", "кошка", "лошадь" }), вы можете рассмотреть это решение. Я подумал об этом и должен сказать, что не использую это вообще. Представьте, как ваши коллеги будут любить вас для поиска ошибки, введенной этим методом.

Ответ 4

В вашем случае вы можете сделать:

if (count(array_unique($tstat, $l1stat, $l2stat, $l3stat)) == 1 //Check if all share the same value (i.e., number of unique values is 1
&& $tstat == 'no_prices')) //If everything is the same and $stat == 'no_prices', then everything is 'no_prices'
{

}

Ответ 5

<?php
$tstat = $l1stat = $l2stat = $l3stat = 'no_prices';
$testVars = array($tstat,$l1stat,$l2stat,$l3stat);

if(count(array_filter($testVars, function($x) { return $x === 'no_prices'; })) == count($testVars))
{
        print("Correct");
}

Использовать array_filter с анонимным обратным вызовом и проверить, больше ли его длина, равна исходному массиву, то есть все условия, переданные,

или если длина больше нуля, то есть любое одно условие, прошедшее

Ответ 6

Нет, этот код не будет работать:

if (($tstat&&$l1stat&&$l2stat&&$l3stat)=='no_prices')
{
    //do something
}

Почему? Потому что условие в круглых скобках проверяет результат сам - вы сравниваете логическое значение с строкой. Итак, в псевдокоде, вот как выглядит ваш код:

if ( ($tstat is true, $l1stat is true, $l2stat is true, $l3stat is true) == 'no_prices' )
     ^                         whole thing returns true                ^    ^   true  ^

Если вы этого не сделаете, вы можете использовать count() и array_unique():

if ($tstat == 'no_prices' && count(array_unique(array($tstat, $l1stat, $l2stat, $l3stat))) == 1)

Ответ 7

попробуйте следующее:

$arr = array($tstat,$l1stat,...); //make an array
$arr =array_unique($arr);//unique this array

if(count($arr) == 1 && $arr[0] = 'no_prices'){ // check if only one array element have with same value
    echo "got it";
}

Ответ 8

Ответ "нет". Там нет стенограммы для данного условия, которое сделает ваш код более читаемым, что должно быть вашим главным приоритетом. Вы можете улучшить его, хотя:

define('MYAPP_NO_PRICES', 'no_prices');

if ($tstat === MYAPP_NO_PRICES
        && $l1stat === MYAPP_NO_PRICES
        && $l2stat === MYAPP_NO_PRICES
        && $l3stat === MYAPP_NO_PRICES) {                                 
    // do something
}

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