PHP:将字符串转换为嵌套数组
Posted
技术标签:
【中文标题】PHP:将字符串转换为嵌套数组【英文标题】:PHP: Converting a String into a Nested Array 【发布时间】:2014-03-16 04:15:12 【问题描述】:我正在使用Laravel
并尝试编写一个工匠命令,该命令接受一个参数 $content,然后需要将其转置为一个数组。例如:
// An example of a value that is being passed in from the CLI and stored as $content
$content = "['div']['div'][0]['h2']['a']";
为了澄清,$content
然后作为函数参数传入,用于从实际结果集中提取值。换句话说,我收到来自 API 的响应,$content
是我需要从响应中提取的值的路径。例如,实现的硬编码版本如下所示:
$result = $report['div']['div'][0]['h2']['a'];
现在,$result
包含我需要处理的值。但是,我正在尝试使这种动态化,因此每次添加新数据源以检查报告时,我都不会重复自己。目前,我有 4 个函数,每个函数都有指向所需结果的硬编码路径;目标是让我可以传入一个包含所需值的路径的参数并重构我的代码,这样我就只有一个函数接受值的路径作为参数。
我希望澄清最终目标以及为什么我只引用键而不是值。
无论如何,回到手头的问题。我尝试了以下不同的变体:
// Attempting to parse the string into an array
$arr = explode("]", trim(str_replace("[","",$content), "]"));
这会产生以下数组:
array (size=5)
0 => string ''div'' (length=5)
1 => string ''div'' (length=5)
2 => string '0' (length=1)
3 => string ''h2'' (length=4)
4 => string ''a'' (length=3)
但是,我需要将数组格式化如下:
$array = ['div']['div'][0]['h2']['a']
我尝试对$arr
执行foreach($array as $element)
并为每个元素执行array_push
,但结果与$arr
相同。
如何遍历字符串并将其解析为数组?此外,我需要 0 保留为索引,而不是类型转换为字符串。最后一点,$content
的值每次都会完全不同,所以我需要它非常灵活。唯一保持不变的部分是 [
和 ]
将始终封装密钥。
我很想听听其他人将如何解决这个看似微不足道的问题(我已经离开编程几年了,显然忘记的比我愿意承认的要多;))。老实说,我认为 str_replace 和 explode 将为我提供我所期待的结果......
但是,在重新阅读 php.net/explode 文档后,它总是会将每个元素转换为字符串(从而覆盖我的 0 索引),我不知道如何将其转换为嵌套数组,而是一个简单的扁平数组。
我期待您的建议和见解。谢谢。
编辑:
包括使用参数的函数以帮助提供更高的清晰度。
private function yql_check_website($url, $xpath, $content)
require_once('../vendor/OAuth.php');
$statement = "select * from html where url='$url' and xpath='$xpath' ";
$cc_key = $this->key;
$cc_secret = $this->secret;
$url = "http://query.yahooapis.com/v1/public/yql";
$args = array();
$args["q"] = $statement;
$args["format"] = "json";
$consumer = new OAuthConsumer($cc_key, $cc_secret);
$request = OAuthRequest::from_consumer_and_token($consumer, NULL,"GET", $url, $args);
$request->sign_request(new OAuthSignatureMethod_HMAC_SHA1(), $consumer, NULL);
$url = sprintf("%s?%s", $url, OAuthUtil::build_http_query($args));
$url .= "&env=store://datatables.org/alltableswithkeys";
$ch = curl_init();
$headers = array($request->to_header());
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$rsp = curl_exec($ch);
$report = json_decode($rsp, true);
// Dynamically inspect the $report object for the xpath content
$result = $report . $content;
unset($report);
return $result;
所以,$report 包含整个 API 响应,但我唯一需要的是 $report['div']['div'][0]['h2']['a']
中提供的内容(至少对于这个示例,我正在抓取的每个报告的路径都不同) .因此,我尝试将命令行参数转换为数组的原因是,它可以在上面调用 $content
的代码中使用,以便导航 API 的响应并从该段返回值。
我希望这更有意义。而且,如果有更好的方法来实现这一最终目标,请随时提及。我可能采取了错误的方法...
【问题讨论】:
$array = ['div']['div'][0]['h2']['a']
没有意义。你有一堆钥匙,但没有价值。
你想让你的 $array 像:$array[0] = ['div'], $array[1] = ['div'], $array[2] = ['0']...
?
@meager,我已经更新了问题以澄清为什么我只引用键。
@DroBuddy,我不明白,你的字符串是什么样的?
@Akshat,不完全是。它确实是 API 响应的路径,因此我需要将其格式化为 ['div']['div'][0]['h2']['a']
以便访问 ['a']
的值。
【参考方案1】:
Laravel 有一些数组访问方法,提供对数组的“点”访问,包括 array_get。方法原型如下所示:
function array_get(array $array, string $key, mixed $default = null)
所以,在你的情况下,你可以写:
$results = array_get($report, "div.div.0.h2.a");
【讨论】:
【参考方案2】:这是你想要的吗?
$str = "['div']['div'][0]['h2']['a']";
$str = preg_split('/]\[/', substr(str_replace("'", "", $str), 1, -1));
print_r($str);
Array (
[0] => div
[1] => div
[2] => 0
[3] => h2
[4] => a
)
【讨论】:
这很接近,但我需要它是多维的,所以它就像 array( 'div' => array ( 'div' => 'array( "0" => array( "h2 " => array("a") ) ) 。但是,这让我很好地了解了如何去做。【参考方案3】:你可以在这里使用 preg_match_all..
$content = "['div']['div'][0]['h2']['a']";
$expression = /\['([a-zA-Z0-9]+)\']/;
$results = preg_match_all( $expression, $content, $matches );
print_r( $matches );
如果你必须让数组像你所说的那样,你可以做这样的事情(对于初学者来说 - 这有点难看,虽然它是......)
// array( ['div']['div'][0]['h2']['a']
// visualizing...
// array( 'div' => array ( 'div' => 'array( "0" => array( "h2" => array( "a") ) ) ) );
function createDepth( $source, $currentKey, $nextDepth = null )
if( !is_array( $nextDepth ) )
$source[] = array( $currentKey => $nextDepth );
else
$nextKey = array_shift( $nextDepth );
$source[] = createDepth( array( $currentKey => array() ), $nextKey, $nextDepth );
return source;
// Edit: doh, unset the first key..
unset( $matches[0] );
// Continue from here.
$currentKey = array_shift( $matches );
$holder = array();
$final = createDepth( $holder, $currentKey, $matches);
print_r( $final );
注意:以上所有内容均未经测试...
【讨论】:
我会试一试,然后告诉你结果如何。谢谢,乔纳森。 嗯,最终返回了Array ( [0] => Array ( [0] => ['div'] [1] => ['div'] [2] => ['a'] ) [1] => Array ( [0] => div [1] => div [2] => a ) )
,但我认为你在这里有所作为。我将尝试使用preg_match_all
,看看是否可以调整表达式以提供我正在寻找的结果。感谢您为我指明了一个坚实的方向。如果我能得到它,我很乐意接受这个作为答案。
酷。请务必查看我编辑的答案...创建了一个递归函数来构建它。虽然它未经测试(我在编辑器中构建了它,并且在一年多的时间里没有真正编写过 PHP 代码,呵呵)
有趣...你说得对,这有点难看,但似乎有道理。我会试一试,看看我能做些什么。再次感谢。以上是关于PHP:将字符串转换为嵌套数组的主要内容,如果未能解决你的问题,请参考以下文章