这是我拥有的数据结构(它是为了更清晰的理解而简化):
• USA
• Alabama
• Montgomery
• Birmingham
• Arizona
• Phoenix
• Mesa
• Gilbert
• Germany
• West Germany
• Bonn
• Cologne
我需要返回给定节点的所有路径 - 即:如果用户输入Arizona
,我需要返回USA → Arizona
。如果输入Birmingham
,我需要返回USA → Alabama → Birmingham
。
在PHP中是否有简单的方法来搜索这样的结构?
答案 0 :(得分:2)
如果您没有庞大的数据结构,则可以使用XML解析。它众所周知且易于实施。它具有访问父元素的期望能力。
这是一个简单的例子:
$xml = <<<XML
<list>
<state name="USA">
<region name="Alabama">
<city name="Montgomery" />
<city name="Birmingham" />
</region>
<region name="Arizona">
<city name="Phoenix" />
<city name="Mesa" />
<city name="Gilbert" />
</region>
</state>
<state name="Germany">
<region name="West Germany">
<city name="Bonn" />
<city name="Cologne" />
</region>
</state>
</list>
XML;
$doc = new \DOMDocument;
$doc->preserveWhiteSpace = false;
$doc->loadXML($xml);
$xpath = new \DOMXPath($doc);
// XPath query to match all elements with
// attribute name equals to your searched phrase
$locations = $xpath->query("//*[@name='Cologne']");
function parse($list) {
$response = [];
foreach ($list as $node) {
$response[] = $node->attributes->getNamedItem('name')->nodeValue;
$parentNode = $node->parentNode;
// traverse up to root element
// root element has no attributes
// feel free to use any other condition, such as checking to element's name
while ($parentNode->hasAttributes()) {
$response[] = $parentNode->attributes->getNamedItem('name')->nodeValue;
$parentNode = $parentNode->parentNode;
}
}
return $response;
}
$parsedLocations = array_reverse(parse($locations));
echo implode(' → ', $parsedLocations), PHP_EOL;
答案 1 :(得分:1)
这是一种可能的策略,逐个构建路径:从数组的第一级开始,检查searc项是否等于键。如果没有,则检查值,否则如果值是数组(is_array()),则使用前缀以递归方式重复搜索。
数据集:
$str = array(
"USA" => array(
"Alabama" => array(
"Montgomery",
"Birmingham"
),
"Arizona" => array(
"Phoenix",
"",
"Gilbert"
),
"West Germany" => array(
"Bonn",
"",
"Cologne"
)
),
"Germany" => array(
"West Germany" => array(
"Bonn",
"Mesa",
"Cologne"
)
)
);
功能:
function getPath($haystack, $needle, $prefix=""){
$path = "";
foreach($haystack as $key=>$value){
if($path!="")break;
if($key===$needle){
return $prefix.$key;
break;
}
elseif($value===$needle) {
return $prefix.$value;
break;
}
elseif(is_array($value)) {
$path.=getPath($value,$needle,$prefix.$key."=>");
}
}
return $path;
}
测试:
echo getPath($str,"Mesa");
如果有重复,您将获得第一个结果。如果找不到搜索词,则会得到一个空字符串。
答案 2 :(得分:1)
因为&#34;数据结构&#34;是非常模糊的,你唯一的暗示是你使用PHP,我会假设你的数据结构&#34;表示以下内容:
[
'USA' =>
[
'Alabama' =>
[
'Montgomery',
'Birmingham'
],
'Arizona' =>
[
'Phoenix',
'Mesa',
'Gilbert'
]
],
'Germany' =>
[
'West Germany' =>
[
'Bonn',
'Cologne'
]
]
]
我认为你希望你的结果在表格中
['USA', 'Alabama', 'Birmingham']
如果不是这种情况,请告知我们您的数据实际可用情况以及您希望如何获得结果。
在PHP中是否有简单的方法来搜索这样的结构?
这取决于你对&#34;简单&#34;的定义 对我来说,适合单一功能的解决方案是简单的&#34; 但是,没有开箱即用的解决方案,您可以在单行中使用。
如果您只需要找到&#34; leafs&#34;,您可以RecursiveIteratorIterator
使用foreach
而不是RecursiveArrayIterator
。{
但是既然你需要找到中间密钥,那它就不是一个选择
this StackOverflow question也是如此。
您可以使用array_walk_recursive
或ArrayIterator
,但在此示例中,除了复杂的事情之外,他们无法真正做foreach
循环所能做的任何事情。<登记/>
所以我只是选择function findMyThing($needle, $haystack) // Keep argument order from PHP array functions
{
// We need to set up a stack array + a while loop to avoid recursive functions for those are evil.
// Recursive functions would also complicate things further in regard of returning.
$stack =
[
[
'prefix' => [],
'value' => $haystack
]
];
// As long as there's still something there, don't stop
while(count($stack) > 0)
{
// Copy the current stack and create a new, empty one
$currentStack = $stack;
$stack = [];
// Work the stack
for($i = 0; $i < count($currentStack); $i++)
{
// Iterate over the actual array
foreach($currentStack[$i]['value'] as $key => $value)
{
// If the value is an array, then
// 1. the key is a string (so we need to match against it)
// 2. we might have to go deeper
if(is_array($value))
{
// We need to build the current prefix list regardless of what we're gonna do below
$prefix = $currentStack[$i]['prefix'];
$prefix[] = $key;
// If the current key, is the one we're looking for, heureka!
if($key == $needle)
{
return $prefix;
}
// Otherwise, push prefix & value onto the stack for the next loop to pick up
else
{
$stack[] =
[
'prefix' => $prefix,
'value' => $value
];
}
}
// If the value is NOT an array, then
// 1. the key is an integer, so we DO NOT want to match against it
// 2. we need to match against the value itself
elseif($value == $needle)
{
// This time append $value, not $key
$prefix = $currentStack[$i]['prefix'];
$prefix[] = $value;
return $prefix;
}
}
}
}
// At this point we searched the entire array and didn't find anything, so we return an empty array
return [];
}
循环:
$path = findMyThing('Alabama', $array);
然后就像
一样使用它remoteView.setViewVisibility(...)
答案 3 :(得分:0)
@Siguza
避免那些邪恶的递归函数
递归不是邪恶的(或eval),并且适用于堆栈
function df($v,array &$in,array &$stack,$search) {
$stack[] = $v;
if ( $v == $search ) {
return [true,$stack];
}
if ( is_array($in) ) {
foreach ($in as $vv => $k) {
if ( is_array($k) ) {
$r = df($vv, $k, $stack, $search);
if ($r[0]) {
return $r;
}
}
else if ($k == $search) {
$stack[] = $k;
return [true,$stack];
}
}
}
array_pop($stack);
return [false,null];
}
用法:
$s = [];
$r = df('',$in,$s,'Bonn');
print_r($r);
$s = [];
$r = df('',$in,$s,'West Germany');
print_r($r);
$s = [];
$r = df('',$in,$s,'NtFound');
print_r($r);
输出:
Array
(
[0] => 1
[1] => Array
(
[0] =>
[1] => Germany
[2] => West Germany
[3] => Bonn
)
)
Array
(
[0] => 1
[1] => Array
(
[0] =>
[1] => Germany
[2] => West Germany
)
)
Array
(
[0] =>
[1] =>
)
答案 4 :(得分:0)
根据你的数据结构。
$data['USA'] = ['Alabama' => ['Montgomery','Birmingham'],'Arizona' => ['Phoenix','Mesa','Gilbert']];
$data['Germany'] = ['West Germany' => ['Bonn','Cologne']];
function getHierarchy($location, $data){
$totalCountries = count($data);
//Get Array Keys of rows eg countries.
$keys = array_keys($data);
$hierarchy= [];
//Loop Through Countries
for($i = 0; $i < $totalCountries; $i++){
//If we have found the country then return it.
if($location == $keys[$i]) return [$keys[$i]];
$hierarchy[] = $keys[$i];
foreach($data[$keys[$i]] as $city => $places){
// if we have found the city then return it with country.
if($city == $location){
$hierarchy[] = $city;
return $hierarchy;
}
// if we have found the place in our places array then return it with country -> city -> place.
if(in_array($location, $places)){
$hierarchy[] = $city;
$hierarchy[] = $location;
return $hierarchy;
}
}
// Reset Hirarcy if we do not found our location in previous country.
$hierarchy = [];
}
}
$found = getHierarchy('Birmingham', $data);
if($found){
echo implode(' -> ', $found);
// Output will be USA -> Alabama -> Birmingham
}
它只能找到一个国家的城市和地点,如果找到任何位置,它将打破整个功能并返回第一个位置与城市和地点。
这是更多改进版本,也可以找到多个位置。 https://gist.github.com/touqeershafi/bf89351f3b226aae1a29
希望它对你有所帮助。