可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
In Python one can do:
foo = {}
assert foo.get('bar', 'baz') == 'baz'
In PHP one can go for a trinary operator as in:
$foo = array();
assert( (isset($foo['bar'])) ? $foo['bar'] : 'baz' == 'baz');
I am looking for a golf version. Can I do it shorter/better in PHP?
回答1:
I just came up with this little helper function:
function get(&$var, $default=null) {
return isset($var) ? $var : $default;
}
Not only does this work for dictionaries, but for all kind of variables:
$test = array('foo'=>'bar');
get($test['foo'],'nope'); // bar
get($test['baz'],'nope'); // nope
get($test['spam']['eggs'],'nope'); // nope
get($undefined,'nope'); // nope
Passing a previously undefined variable per reference doesn't cause a NOTICE
error. Instead, passing $var
by reference will define it and set it to null
. The default value will also be returned if the passed variable is null
. Also note the implicitly generated array in the spam/eggs example:
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
Note that even though $var
is passed by reference, the result of get($var)
will be a copy of $var
, not a reference. I hope this helps!
回答2:
Time passes and PHP is evolving. PHP7 now supports Null coalescing operator:
// 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';
回答3:
use error control operator @ with PHP 5.3 shortcut version of ternary operator
$bar = @$foo['bar'] ?: 'defaultvalue';
回答4:
PHP 5.3 has a shortcut version of ternary operator:
$x = $foo ?: 'defaultvaluehere';
which is basically
if (isset($foo)) {
$x = $foo;
else {
$x = 'defaultvaluehere';
}
Otherwise, no, there's no shorter method.
回答5:
A "slightly" hacky way to do it:
<?php
$foo = array();
var_dump('baz' == $tmp = &$foo['bar']);
$foo['bar'] = 'baz';
var_dump('baz' == $tmp = &$foo['bar']);
http://codepad.viper-7.com/flXHCH
Obviously this isn't really the nice way to do it. But it is handy in other situations. E.g. I often declare shortcuts to GET and POST variables like that:
<?php
$name =& $_GET['name'];
// instead of
$name = isset($_GET['name']) ? $_GET['name'] : null;
PS: One could call this the "built-in ==$_=&
special comparison operator":
<?php
var_dump('baz' ==$_=& $foo['bar']);
PPS: Well, you could obviously just use
<?php
var_dump('baz' == @$foo['bar']);
but that's even worse than the ==$_=&
operator. People don't like the error suppression operator much, you know.
回答6:
I find it useful to create a function like so:
function array_value($array, $key, $default_value = null) {
return is_array($array) && array_key_exists($key, $array) ? $array[$key] : $default_value;
}
And use it like this:
$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 }";
The default value in this case is null
, but you may set it to whatever you need.
I hope it is useful.
回答7:
If you enumerate the default values by key in an array, it can be done this way:
$foo = array('a' => 1, 'b' => 2);
$defaults = array('b' => 55, 'c' => 44);
$foo = array_merge($defaults, $foo);
print_r($foo);
Which results in:
Array
(
[b] => 2
[c] => 44
[a] => 1
)
The more key/value pairs that you enumerate defaults for, the better the code-golf becomes.