我正在寻找php这个问题的已接受答案中提到的解决方案:
javascript - 返回父级,只有与嵌套对象的对象数组中的给定搜索字符串匹配的子级
请找到以下代码:
<?php
$items = array(
'tableData' => array
(
array
(
'booking_name' => 'abc/xyz/123',
'pdg' => 'assure',
'user_area' => 'es st1',
'release' => 'oss72',
'start_date' => '2017-06-20 00:00:00',
'end_date' => '2017-06-23 00:00:00',
'asset_info' => array
(
array
(
'status' => 10,
'manufacturer' => 'Oracle',
'model' => 'HP BL460C GEN8',
'hardware_color' => '#0066b3',
),
array
(
'status' => 11,
'manufacturer' => 'HP',
'model' => 'HP BL460C GEN81',
'hardware_color' => '#0066b3',
)
),
'full_name' => 'Valay Desai',
'email_address' => 'valay@xyz.com',
),
array
(
'booking_name' => 'abc/xyz/123',
'pdg' => 'enm',
'user_area' => 'es st',
'release' => 'oss72',
'start_date' => '2017-06-20 00:00:00',
'end_date' => '2017-06-23 00:00:00',
'asset_info' => array
(
array
(
'status' => 10,
'manufacturer' => 'HP',
'model' => 'HP BL460C GEN8',
'hardware_color' => '#0066b3',
)
),
'full_name' => 'Valay Desai',
'email_address' => 'valay@xyz.com',
)
)
);
function getParentStackComplete($child, $stack) {
$return = array();
foreach ($stack as $k => $v) {
if (is_array($v)) {
// If the current element of the array is an array, recurse it
// and capture the return stack
$stack = getParentStackComplete($child, $v);
// If the return stack is an array, add it to the return
if (is_array($stack) && !empty($stack)) {
$return[] = $v;
}
} else {
// Since we are not on an array, compare directly
if(strpos($v, $child) !== false){
// And if we match, stack it and return it
$return[] = $v;
}
}
}
// Return the stack
return empty($return) ? false: $return;
}
echo "<pre>";
print_r(getParentStackComplete('Oracle', $items['tableData']));
echo "</pre>";
?>
Run Code Online (Sandbox Code Playgroud)
这段代码工作正常。我在getParentStackComplete网上找到了这个函数,修改它以返回整个匹配元素。它递归搜索数组并返回匹配项。
例如,如代码中所示,如果我搜索字符串“Oracle”,它应该返回一个数组,其中包含一个项目,其中只有一个子项(匹配元素)asset_info。我正在寻找的输出是:
Array
(
[0] => Array
(
[booking_name] => abc/xyz/123
[pdg] => assure
[user_area] => es st1
[release] => oss72
[start_date] => 2017-06-20 00:00:00
[end_date] => 2017-06-23 00:00:00
[asset_info] => Array
(
[0] => Array
(
[status] => 10
[manufacturer] => Oracle
[model] => HP BL460C GEN8
[hardware_color] => #0066b3
)
)
[full_name] => Valay Desai
[email_address] => valay@xyz.com
)
)
Run Code Online (Sandbox Code Playgroud)
如果我搜索 string HP BL460C GEN8,它应该返回如下:
Array
(
[0] => Array
(
[booking_name] => abc/xyz/123
[pdg] => assure
[user_area] => es st1
[release] => oss72
[start_date] => 2017-06-20 00:00:00
[end_date] => 2017-06-23 00:00:00
[asset_info] => Array
(
[0] => Array
(
[status] => 10
[manufacturer] => Oracle
[model] => HP BL460C GEN8
[hardware_color] => #0066b3
)
)
[full_name] => Valay Desai
[email_address] => valay@xyz.com
)
[1] => Array
(
'booking_name' => 'abc/xyz/123',
'pdg' => 'enm',
'user_area' => 'es st',
'release' => 'oss72',
'start_date' => '2017-06-20 00:00:00',
'end_date' => '2017-06-23 00:00:00',
'asset_info' => array
(
array
(
'status' => 10,
'manufacturer' => 'HP',
'model' => 'HP BL460C GEN8',
'hardware_color' => '#0066b3',
)
),
'full_name' => 'Valay Desai',
'email_address' => 'valay@xyz.com'
)
)
Run Code Online (Sandbox Code Playgroud)
如何在嵌套数组搜索中返回与父级匹配的子级?
要仅深度搜索叶节点,可以直接通过RecursiveIterator进行递归迭代,其RecursiveIteratorIterator通过RecursiveArrayIterator处理仅叶遍历。
为了使其在此处可见,请使用示例数据上的一个小型搜索示例:
$iterator = new RecursiveArrayIterator($items['tableData']); # 1.
$leafs = new RecursiveIteratorIterator($iterator); # 2.
$search = new RegexIterator($leafs, sprintf('~^%s$~', preg_quote('HP BL460C GEN8', '~'))); # 3.
foreach ($search as $value) { # 4.
var_dump($value);
}
Run Code Online (Sandbox Code Playgroud)
确实如此
foreach搜索并输出值进行演示。并会输出:
string(14) "HP BL460C GEN8"
string(14) "HP BL460C GEN8"
Run Code Online (Sandbox Code Playgroud)
通过三行代码可以有效地设置搜索。
这还不是全部,因为在内部我们foreach仍然有装饰迭代的上下文,您不仅可以访问当前值,还可以访问上三层,即您想要返回的父级:
foreach ($search as $key => $value) {
$parentLevel = 0; # or for relative access: $leafs->getDepth() - 3
$parent = $leafs->getSubIterator($parentLevel)->current();
var_dump($parent);
}
Run Code Online (Sandbox Code Playgroud)
这将输出与搜索匹配的所有父对象。
这可能已经回答了您的问题,所以让我们完整地展示这个示例:
$search = function (array $array, string $term) {
$iterator = new RecursiveArrayIterator($array);
$leafs = new RecursiveIteratorIterator($iterator);
$search = new RegexIterator($leafs, sprintf('~^%s$~', preg_quote($term, '~')));
foreach ($search as $value) {
$parent = $leafs->getSubIterator(0)->current();
yield $parent;
}
};
$matches = $search($items['tableData'], 'HP BL460C GEN8');
foreach ($matches as $index => $match) {
echo $index + 1, ': ';
print_r($match);
}
Run Code Online (Sandbox Code Playgroud)
它的输出:
1: Array
(
[booking_name] => abc/xyz/123
[pdg] => assure
[user_area] => es st1
[release] => oss72
[start_date] => 2017-06-20 00:00:00
[end_date] => 2017-06-23 00:00:00
[asset_info] => Array
(
[0] => Array
(
[status] => 10
[manufacturer] => Oracle
[model] => HP BL460C GEN8
[hardware_color] => #0066b3
)
[1] => Array
(
[status] => 11
[manufacturer] => HP
[model] => HP BL460C GEN81
[hardware_color] => #0066b3
)
)
[full_name] => Valay Desai
[email_address] => valay@xyz.com
)
2: Array
(
[booking_name] => abc/xyz/123
[pdg] => enm
[user_area] => es st
[release] => oss72
[start_date] => 2017-06-20 00:00:00
[end_date] => 2017-06-23 00:00:00
[asset_info] => Array
(
[0] => Array
(
[status] => 10
[manufacturer] => HP
[model] => HP BL460C GEN8
[hardware_color] => #0066b3
)
)
[full_name] => Valay Desai
[email_address] => valay@xyz.com
)
Run Code Online (Sandbox Code Playgroud)
但是,如果您可能希望将parentsasset_info数组减少为仅包含这些匹配项,而不仅仅是包含匹配项的所有parents,该怎么办?如果是这样,则需要创建一个结果数组,其中仅包含asset_info匹配条目中的那些条目。这需要跟踪匹配的父母,以便asset_info可以将 matches 添加到他们的结果中。
因为这需要处理同一父级的所有匹配资产,然后仅向该父级提供这些匹配项。因此,匹配将在其父级中分组,因此这是一种聚合函数,因此需要管理更多的事情,因为它需要跟踪父级是否已经拥有所有匹配:
$search = function (array $array, string $term) {
$iterator = new RecursiveArrayIterator($array);
$leafs = new RecursiveIteratorIterator($iterator);
/* @var $search RecursiveIteratorIterator|RegexIterator - $search is a decorator of that type */
$search = new RegexIterator($leafs, sprintf('~^%s$~', preg_quote($term, '~')));
# initialize
$match = $lastId = null;
foreach ($search as $key => $value) {
$parentId = $search->getSubIterator(0)->key();
if ($lastId !== $parentId && $match) {
yield $match;
$match = null;
}
$lastId = $parentId;
if (empty($match)) {
# set match w/o asset_info as yet not matched
$match = $search->getSubIterator(0)->current();
$match['asset_info'] = [];
}
# add matched asset into the matched asset_info
$match['asset_info'][] = $search->getSubIterator(2)->current();
}
$match && yield $match;
};
$matches = $search($items['tableData'], 'HP BL460C GEN8');
foreach ($matches as $index => $match) {
echo $index + 1, ': ';
print_r($match);
}
Run Code Online (Sandbox Code Playgroud)
在您的情况下,输出给出:
1: Array
(
[booking_name] => abc/xyz/123
[pdg] => assure
[user_area] => es st1
[release] => oss72
[start_date] => 2017-06-20 00:00:00
[end_date] => 2017-06-23 00:00:00
[asset_info] => Array
(
[0] => Array
(
[status] => 10
[manufacturer] => Oracle
[model] => HP BL460C GEN8
[hardware_color] => #0066b3
)
)
[full_name] => Valay Desai
[email_address] => valay@xyz.com
)
2: Array
(
[booking_name] => abc/xyz/123
[pdg] => enm
[user_area] => es st
[release] => oss72
[start_date] => 2017-06-20 00:00:00
[end_date] => 2017-06-23 00:00:00
[asset_info] => Array
(
[0] => Array
(
[status] => 10
[manufacturer] => HP
[model] => HP BL460C GEN8
[hardware_color] => #0066b3
)
)
[full_name] => Valay Desai
[email_address] => valay@xyz.com
)
Run Code Online (Sandbox Code Playgroud)
请注意第一个匹配项中条目数量的细微差别asset_info,即一个而不是之前的两个。
试试这个代码。
function getParentStackComplete( $search, $stack ){
$results = array();
foreach( $stack as $item ){
if( is_array( $item ) ){
if( array_filter($item, function($var) use ($search) { return ( !is_array( $var ) )? stristr( $var, $search ): false; } ) ){
//echo 'test';
$results[] = $item;
continue;
}else if( array_key_exists('asset_info', $item) ){
$find_assets = array();
foreach( $item['asset_info'] as $k=>$v ){
//echo 'abc ';
if( is_array( $v ) && array_filter($v, function($var) use ($search) { return stristr($var, $search); }) ){
$find_assets[] = $v;
}
}
if( count( $find_assets ) ){
$temp = $item;
$temp['asset_info'] = $find_assets;
$results[] = $temp;
}
}
}
}
return $results;
}
Run Code Online (Sandbox Code Playgroud)