我的项目中有一个分层数组,如下所示:
$Array = array(
array(
'Id' => 1,
'Title' => 'Some Text1',
'Children' => array(
array(
'Id' => 11,
'Title' => 'Some Text11',
'Children' => array(
array(
'Id' => 111,
'Title' => 'Some Text111',
),
array(
'Id' => 112,
'Title' => 'Some Text112',
'Children' => array(
array(
'Id' => 1121,
'Title' => 'Some Text1121',
)
)
)
)
),
array(
'Id' => 12,
'Title' => 'Some Text12',
'Children' => array(
array(
'Id' => 121,
'Title' => 'Some Text121',
)
)
)
)
),
array(
'Id' => 2,
'Title' => 'Some Text2',
)
);
我想搜索带有传入字符串(例如
Title
)的Some Text1121
列,并返回由Id
值组成的路径。
如果搜索的是
Some Text1121
,我想返回:
1 -> 11 -> 112 -> 1121
或者当我搜索“Some”字符串时,返回数组中的所有 Id 路径。
我很快就给你写了一些东西。它并不完美,但你明白了:
<?php
function searchRec($haystack, $needle, $pathId = Array(), $pathIndex = Array()) {
foreach($haystack as $index => $item) {
// add the current path to pathId-array
$pathId[] = $item['Id'];
// add the current index to pathIndex-array
$pathIndex[] = $index;
// check if we have a match
if($item['Title'] == $needle) {
// return the match
$returnObject = new stdClass();
// the current item where we have the match
$returnObject->match = $item;
// path of Id's (1, 11, 112, 1121)
$returnObject->pathId = $pathId;
// path of indexes (0,0,1,..) - you might need this to access the item directly
$returnObject->pathIndex = $pathIndex;
return $returnObject;
}
if(isset($item['Children']) && count($item['Children']>0)) {
// if this item has children, we call the same function (recursively)
// again to search inside those children:
$result = searchRec($item['Children'], $needle, $pathId, $pathIndex);
if($result) {
// if that search was successful, return the match-object
return $result;
}
}
}
return false;
}
// useage:
$result = searchRec($Array, "Some Text11");
var_dump($result);
// use
echo implode(" -> ", $result->pathId);
// to get your desired 1 -> 11 -> 112
编辑:重写以使函数实际上返回一些东西。现在它返回一个带有匹配项的对象、Id 的路径和(数组)索引的路径。
要在分层数组中的任何级别上搜索部分匹配,请使用递归方法并搜索合格的子字符串。 当找到匹配时,将累积的关键路径推送到结果数组中,该结果数组将返回到调用脚本。
此脚本将返回一个包含零个或多个合格标题的 id 路径的数组。 演示
function pathFinder(array $array, string $find, string $path = ''): array {
$paths = [];
foreach ($array as $item) {
$currentPath = $path . ($path ? ' -> ' : '') . $item['Id'];
if (str_contains($item['Title'], $find)) {
$paths[] = $currentPath;
}
if (isset($item['Children'])) {
array_push(
$paths,
...pathFinder($item['Children'], $find, $currentPath)
);
}
}
return $paths;
}
var_export(
pathFinder($array, 'Some Text111')
);