Php 算法 - 如何在没有 eval 的情况下实现这一点
我有一个类,它通过使用words.separated.by.dots 键来保存数据存储/访问数据,其行为如下:
$object = new MyArray()
$object->setParam('user.name','marcelo');
$object->setParam('user.email','[email protected]');
$object->getParams();
/*
array(
'user' => array(
'name' => 'marcelo',
'email' => '[email protected]'
)
);
*/
它正在工作,但方法 unsetParam() 的实现非常糟糕。发生这种情况是因为我不知道如何在没有 eval() 函数的情况下实现这一目标。尽管它有效,但我发现这是一个非常具有挑战性的算法,并且您可能会发现尝试在不使用 eval() 的情况下实现这一目标很有趣。
class MyArray {
/**
* @param string $key
* @return Mura_Session_Abstract
*/
public function unsetParam($key)
{
$params = $this->getParams();
$tmp = $params;
$keys = explode('.', $key);
foreach ($keys as $key) {
if (!isset($tmp[$key])) {
return $this;
}
$tmp = $tmp[$key];
}
// bad code!
$eval = "unset(\$params['" . implode("']['", $keys) . "']);";
eval($eval);
$this->setParams($params);
return $this;
}
}
测试方法:
public function testCanUnsetNestedParam()
{
$params = array(
'1' => array(
'1' => array(
'1' => array(
'1' => 'one',
'2' => 'two',
'3' => 'three',
),
'2' => array(
'1' => 'one',
'2' => 'two',
'3' => 'three',
),
)
),
'2' => 'something'
);
$session = $this->newSession();
$session->setParams($params);
unset($params['1']['1']['1']);
$session->unsetParam('1.1.1');
$this->assertEquals($params, $session->getParams());
$this->assertEquals($params['1']['1']['2'], $session->getParam('1.1.2'));
}
I have a class that keeps data stores/access data by using words.separated.by.dots keys and it behaves like the following:
$object = new MyArray()
$object->setParam('user.name','marcelo');
$object->setParam('user.email','[email protected]');
$object->getParams();
/*
array(
'user' => array(
'name' => 'marcelo',
'email' => '[email protected]'
)
);
*/
It is working, but the method unsetParam() was horribly implemented. That happened because i didn't know how to achieve that without eval() function. Although it is working, I found that it was a really challenging algorithm and that you might find fun trying to achieve that without eval().
class MyArray {
/**
* @param string $key
* @return Mura_Session_Abstract
*/
public function unsetParam($key)
{
$params = $this->getParams();
$tmp = $params;
$keys = explode('.', $key);
foreach ($keys as $key) {
if (!isset($tmp[$key])) {
return $this;
}
$tmp = $tmp[$key];
}
// bad code!
$eval = "unset(\$params['" . implode("']['", $keys) . "']);";
eval($eval);
$this->setParams($params);
return $this;
}
}
The test method:
public function testCanUnsetNestedParam()
{
$params = array(
'1' => array(
'1' => array(
'1' => array(
'1' => 'one',
'2' => 'two',
'3' => 'three',
),
'2' => array(
'1' => 'one',
'2' => 'two',
'3' => 'three',
),
)
),
'2' => 'something'
);
$session = $this->newSession();
$session->setParams($params);
unset($params['1']['1']['1']);
$session->unsetParam('1.1.1');
$this->assertEquals($params, $session->getParams());
$this->assertEquals($params['1']['1']['2'], $session->getParam('1.1.2'));
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
是这个吗?
Is this it?
如果您仅在
getParams
方法中拆分为多维数组,则可以使代码更简单:You could make your code easier if you only split to a multidimension array in your
getParams
method:@gustavotkg 和@Esailija 都提供了一些很棒的想法。这是另一种简单、易于理解且简短的方法,可以完全避免 unset() (可以得到 在某些情况下很奇怪)。
当然,当 $params 限制为小于 1k-10k 值时(这在 CPU/内存部门开始变得有点昂贵),这将是最有用的:
@gustavotkg and @Esailija have both offered some great ideas. Here is another simple, easy to understand, and short approach that avoids unset() altogether (which can get quirky in some cases).
This would, of course, be most useful when $params is limited to less than, say, 1k-10k of values (which starts to get a bit pricey in the CPU/memory dept):