Есть ли лучший способ PHP для получения значения по умолчанию по ключу из массива (словарь)?
В Python можно сделать:
foo = {}
assert foo.get('bar', 'baz') == 'baz'
В PHP можно использовать тройной оператор, например:
$foo = array();
assert( (isset($foo['bar'])) ? $foo['bar'] : 'baz' == 'baz');
Я ищу версию для гольфа. Могу ли я сделать это короче / лучше в PHP?
7 ответов
Я только что придумал эту маленькую вспомогательную функцию:
function get(&$var, $default=null) {
return isset($var) ? $var : $default;
}
Это работает не только для словарей, но и для всех видов переменных:
$test = array('foo'=>'bar');
get($test['foo'],'nope'); // bar
get($test['baz'],'nope'); // nope
get($test['spam']['eggs'],'nope'); // nope
get($undefined,'nope'); // nope
Передача ранее неопределенной переменной по ссылке не вызывает NOTICE
ошибка. Вместо этого, проходя $var
по ссылке определит его и установит null
, Значение по умолчанию также будет возвращено, если переданная переменная null
, Также обратите внимание на неявно сгенерированный массив в примере спам / яйца:
json_encode($test); // {"foo":"bar","baz":null,"spam":{"eggs":null}}
$undefined===null; // true (got defined by passing it to get)
isset($undefined) // false
get($undefined,'nope'); // nope
Обратите внимание, что даже если $var
передается по ссылке, результат get($var)
будет копия $var
не ссылка. Надеюсь, это поможет!
Время идет, а PHP развивается. PHP7 теперь поддерживает оператор объединения Null:
// Fetches the value of $_GET['user'] and returns 'nobody'
// if it does not exist.
$username = $_GET['user'] ?? 'nobody';
// This is equivalent to:
$username = isset($_GET['user']) ? $_GET['user'] : 'nobody';
// Coalescing can be chained: this will return the first
// defined value out of $_GET['user'], $_POST['user'], and
// 'nobody'.
$username = $_GET['user'] ?? $_POST['user'] ?? 'nobody';
использовать оператор контроля ошибок @ с краткой версией PHP 5.3 для троичного оператора
$bar = @$foo['bar'] ?: 'defaultvalue';
Я считаю полезным создать такую функцию:
function array_value($array, $key, $default_value = null) {
return is_array($array) && array_key_exists($key, $array) ? $array[$key] : $default_value;
}
И используйте это так:
$params = array('code' => 7777, 'name' => "Cloud Strife");
$code = array_value($params, 'code');
$name = array_value($params, 'name');
$weapon = array_value($params, 'weapon', "Buster Sword");
$materia = array_value($params, 'materia');
echo "{ code: $code, name: $name, weapon: $weapon, materia: $materia }";
Значение по умолчанию в этом случае null
, но вы можете установить его на то, что вам нужно.
Я надеюсь, что это полезно.
PHP 5.3 имеет сокращенную версию тернарного оператора:
$x = $foo ?: 'defaultvaluehere';
что в основном
if (isset($foo)) {
$x = $foo;
else {
$x = 'defaultvaluehere';
}
В противном случае, нет более короткого метода.
"Немного" хакерский способ сделать это:
<?php
$foo = array();
var_dump('baz' == $tmp = &$foo['bar']);
$foo['bar'] = 'baz';
var_dump('baz' == $tmp = &$foo['bar']);
http://codepad.viper-7.com/flXHCH
Очевидно, это не очень хороший способ сделать это. Но это удобно в других ситуациях. Например, я часто объявляю ярлыки для переменных GET и POST:
<?php
$name =& $_GET['name'];
// instead of
$name = isset($_GET['name']) ? $_GET['name'] : null;
PS: можно назвать это "встроенным ==$_=&
специальный оператор сравнения ":
<?php
var_dump('baz' ==$_=& $foo['bar']);
PPS: Ну, вы могли бы просто использовать
<?php
var_dump('baz' == @$foo['bar']);
но это даже хуже чем ==$_=&
оператор. Знаете, людям не очень нравится оператор подавления ошибок.
Если вы перечислите значения по умолчанию по ключу в массиве, это можно сделать следующим образом:
$foo = array('a' => 1, 'b' => 2);
$defaults = array('b' => 55, 'c' => 44);
$foo = array_merge($defaults, $foo);
print_r($foo);
Что приводит к:
Array
(
[b] => 2
[c] => 44
[a] => 1
)
Чем больше пар ключ / значение, для которых вы перечисляете значения по умолчанию, тем лучше становится код-гольф.
"Marc B" предложил решение использовать тройной ярлык $x = $foo ?: 'defaultvaluehere';
но это все еще дает уведомления. Наверное это опечатка, может он имел ввиду?? или это было написано до выпуска PHP 7. Согласно тройному описанию:
Начиная с PHP 5.3, можно опустить среднюю часть троичного оператора. выражение
expr1 ?: expr3
возвращаетсяexpr1
еслиexpr1
оцениваетTRUE
, а такжеexpr3
иначе.
Но это не использует isset
внутри и производит уведомления. Во избежание уведомлений лучше использовать Null Coalescing Operator ??
который использует isset
внутри него. Доступно в PHP 7.
Выражение (expr1) (expr2) оценивается как expr2, если expr1 равен NULL, и expr1 в противном случае. В частности, этот оператор не выдает уведомление, если левое значение не существует, как и isset(). Это особенно полезно для ключей массива.
Пример #5 Назначение значения по умолчанию
<?php
// Example usage for: Null Coalesce Operator
$action = $_POST['action'] ?? 'default';
// The above is identical to this if/else statement
if (isset($_POST['action'])) {
$action = $_POST['action'];
} else {
$action = 'default';
}
?>