通过引用取消设置数组的元素
Posted
技术标签:
【中文标题】通过引用取消设置数组的元素【英文标题】:unset a element of an array via reference 【发布时间】:2011-04-09 10:17:29 【问题描述】:我可以通过引用方法访问多维数组中的任何位置。我可以改变它的价值。例如:
$conf = array(
'type' => 'mysql',
'conf' => array(
'name' => 'mydatabase',
'user' => 'root',
'pass' => '12345',
'host' => array(
'127.0.0.1',
'88.67.45.123',
'129.34.123.55'
),
'port' => '3306'
)
);
$value = & $this->getFromArray('type.conf.host');
$value = '-- changed ---';
// result
$conf = array(
'type' => 'mysql',
'conf' => array(
'name' => 'mydatabase',
'user' => 'root',
'pass' => '12345',
'host' => '-- changed ---'
'port' => '3306'
)
);
但是,我不能破坏那个部分:
// normally success
unset($conf['type']['conf']['host']);
// fail via reference
$value = & $this->getFromArray('type.conf.host');
unset($value);
有解决办法吗?
【问题讨论】:
【参考方案1】:好的,我认为更好的答案。为了取消设置,您应该获取对容器数组的引用,然后取消设置数组中的元素;
即
$value = & $this->getFromArray('type.conf');
unset $value['host'];
【讨论】:
是的 - 如果你引用数组中的值,php 允许你通过该引用更新值,但它不允许你通过unset
ing 删除数组条目参考资料。参见例如3v4l.org/OsYck【参考方案2】:
引用不像硬链接。如果您取消设置引用,这不会取消设置原点值。
<?php
$a = 5;
xdebug_debug_zval('a'); // a: (refcount=1, is_ref=0), int 5
$b = &$a;
xdebug_debug_zval('a'); // a: (refcount=2, is_ref=1), int 5
xdebug_debug_zval('b'); // b: (refcount=2, is_ref=1), int 5
unset($b);
xdebug_debug_zval('a'); // a: (refcount=1, is_ref=0), int 5
为什么不写一个抽象数据(数组)的Config
类?由于对象总是通过引用传递,因此您无需自行处理。
class Config
// ...
$config = new Config(array(
'db' => array(
'name' => 'mydatabase',
'user' => 'root',
'pass' => '12345',
)
));
$config->get('db.user');
$config->set('db.user', 'newuser');
$config->unset('db.user');
//...
【讨论】:
参考文献类似于硬链接。如果您更改第二个引用,它会更改第一个引用中的值。如果删除第二个引用,它不会删除第一个。这非常类似于文件系统中的硬链接。【参考方案3】:为我的框架创建一些函数,认为它们会阻碍你。
1. 数组中的函数设置值使用导航参考 - 如果引用以名称/键结尾,则此名称/键将等于设置值 - 如果引用以分隔符结尾,则姓氏/键将是具有设置值的数组
function array_reference_set($input_arr=array(),$reference='',$delimiter='->',$set_var='')
switch ($reference)
case (is_string($reference)):
$reference = array_reverse(explode($delimiter, $reference),true);
break;
case (!is_array($reference)):
return $input_arr;
$key = array_pop($reference);
if (count($reference)<1)
if($key!='')
$input_arr[$key] = $set_var;
elseif (!is_array($input_arr) && $key=='')
$input_arr = array($set_var);
elseif ($key=='')
$input_arr[] = $set_var;
else
if (!is_array($input_arr))
$input_arr = array($key=>array());
if (isset($input_arr[$key]))
$input_arr[$key] = $this->array_reference_set($input_arr[$key],$reference,$delimiter,$set_var);
else
$input_arr[$key] = $this->array_reference_set(array(),$reference,$delimiter,$set_var);
return $input_arr;
$arr = array_reference_set(array(),'a->b->c','->','test');
//equal
$arr = array('a'=>array('b'=>array('c'=>'test')));//or
$arr['a']['b']['c'] = 'test';
$arr = array_reference_set(array(),'a->b->c->','->','test');
//equal
$arr = array('a'=>array('b'=>array('c'=>array('test'))));//or
$arr['a']['b']['c'][] = 'test';
2。函数使用引用从数组中设置未设置值
- 如果引用结尾是分隔符,那么将在分隔符之前使用名称/键取消设置变量 - 使用此函数的一瞬间:您需要通过函数返回的结果更新数组(在代码示例的末尾)
function array_reference_unset($input_arr=array(),$reference='',$delimiter='->')
switch ($reference)
case (is_string($reference)):
$reference = array_reverse(explode($delimiter, $reference),true);
break;
case (!is_array($reference)):
return $input_arr;
$key = array_pop($reference);
if (count($reference)<1 && is_string($key))
if ($key!='')
unset($input_arr[$key]);
else
return false;
else
if (isset($input_arr[$key]))
$ret = $this->array_reference_unset($input_arr[$key],$reference,$delimiter);
if ($ret!==false)
$input_arr[$key] = $ret;
else
unset ($input_arr[$key]);
return $input_arr;
$arr = array('a'=>array('b'=>array('c'=>'test')));// test subject
$arr = array_reference_unset($arr,'a->b->c','->');//and
$arr = array_reference_unset($arr,'a->b->c->','->');
//equal
unset($arr['a']['b']['c']);
附言对不起我纯英语
【讨论】:
【参考方案4】:这是我取消设置嵌套键的函数
public function unsetKey(string $dotSeparatedKey)
$keys = explode('.', $dotSeparatedKey);
$pointer = &$this->data;
$current = false; // just to make code sniffer happy
// we traverse all but the last key
while (($current = array_shift($keys)) && (count($keys) > 0))
// if some key is missing all the subkeys will be already unset
if (!array_key_exists($current, $pointer))
// is already unset somewhere along the way
return;
// set pointer to new, deeper level
// called for all but last key
$pointer = &$pointer[$current];
// handles empty input string
if ($current)
// we finally unset what we wanted
unset($pointer[$current]);
【讨论】:
以上是关于通过引用取消设置数组的元素的主要内容,如果未能解决你的问题,请参考以下文章