从多维嵌套数组中删除数组的一部分
Removing part of an array from a multidimensional nested array
我有一个像这样的四层嵌套数组:
$array = [
[
'website' => [
'id' => 'one'
],
'children' => [
[
'website' => [
'id' => 'one.one'
],
'children' => [
[
'website' => [
'id' => 'one.one.one'
],
'children' => [
[
'website' => [
'id' => 'one.one.one.one'
],
'children' => []
],
[
'website' => [
'id' => 'one.one.one.two'
],
'children' => []
]
]
],
[
'website' => [
'id' => 'one.one.two'
],
'children' => [
[
'website' => [
'id' => 'one.one.two.one'
],
'children' => []
],
[
'website' => [
'id' => 'one.one.two.two'
],
'children' => []
]
]
]
]
],
[
'website' => [
'id' => 'one.two'
],
'children' => [
[
'website' => [
'id' => 'one.two.one'
],
'children' => [
[
'website' => [
'id' => 'one.two.one.one'
],
'children' => []
],
[
'website' => [
'id' => 'one.two.one.two'
],
'children' => []
]
]
],
[
'website' => [
'id' => 'one.two.two'
],
'children' => [
[
'website' => [
'id' => 'one.two.two.one'
],
'children' => []
],
[
'website' => [
'id' => 'one.two.two.two'
],
'children' => []
]
]
]
]
]
]
]
];
现在,我想根据一些规则删除一些数组元素。为简单起见,假设我们要删除 'id' 等于 one.one.two
或 one.two.one
.
的数组元素
我正在研究 Whosebug 上提供的一些答案,并试图应用它们来解决我的问题,但没有做太多。最棘手的事情是取消数组中不是数组中最远点的部分。
我正在尝试这样做以记录我想在哪个级别删除数组,然后尝试使用这些数组索引取消设置它们。
$pointer = [];
foreach($array as $key => $level1) {
$level1pointer = $key;
$pointer[] = markToDelete($level1, $level1pointer);
foreach($level1['children'] as $key => $level2) {
$level2pointer = $key;
$pointer[] = markToDelete($level2, $level1pointer, $level2pointer);
foreach($level2['children'] as $key => $level3) {
$level3pointer = $key;
$pointer[] = markToDelete($level3, $level1pointer, $level2pointer, $level3pointer);
foreach($level3['children'] as $key => $level4) {
$level4pointer = $key;
$pointer[] = markToDelete($level4, $level1pointer, $level2pointer, $level3pointer, $level4pointer);
}
}
}
}
function markToDelete($array, $level1 = null, $level2 = null, $level3 = null, $level4 = null) {
$exclusionList = [
'one.one.two',
'one.two.one'
];
if (!empty($array['website']) && in_array($array['website']['id'], $exclusionList)) {
print_r('marking for deletion: '. $array['website']['id'] . PHP_EOL);
return [
'id' => $array['website']['id'],
'level1' => $level1,
'level2' => $level2,
'level3' => $level3,
'level4' => $level4
];
}
return [];
}
我也试过这样使用迭代器:
$it = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($array), \RecursiveIteratorIterator::LEAVES_ONLY);
$newArray = [];
foreach($it as $key => $value) {
$exclusionList = [
'one.one.two',
'one.two.one'
];
if(!in_array($value, $exclusionList)) {
print_r(sprintf('value: %s is ready to be deleted', $value).PHP_EOL);
$newArray[] = $value;
}
}
但是我需要一种方法在遍历迭代器时取消设置数组。
我想要这样的输出:
$array = [
[
'website' => [
'id' => 'one'
],
'children' => [
[
'website' => [
'id' => 'one.one'
],
'children' => [
[
'website' => [
'id' => 'one.one.one'
],
'children' => [
[
'website' => [
'id' => 'one.one.one.one'
],
'children' => []
],
[
'website' => [
'id' => 'one.one.one.two'
],
'children' => []
]
]
],
]
],
[
'website' => [
'id' => 'one.two'
],
'children' => [
[
'website' => [
'id' => 'one.two.two'
],
'children' => [
[
'website' => [
'id' => 'one.two.two.one'
],
'children' => []
],
[
'website' => [
'id' => 'one.two.two.two'
],
'children' => []
]
]
]
]
]
]
]
];
如果能帮助我更有效地解决此问题,我将不胜感激。谢谢。
这是一个递归函数,可以执行您想要的操作。它遍历数组,寻找其网站 ID 在要删除的 ID 列表中的子项并取消设置它们。请注意,由于您有额外的 top-level 数组,您需要在这些值上迭代函数。
function delete_entries(&$array, $ids_to_delete) {
foreach ($array['children'] as $index => &$child) {
if (in_array($child['website']['id'], $ids_to_delete)) {
unset($array['children'][$index]);
}
delete_entries($child, $ids_to_delete);
}
}
foreach ($array as &$arr) {
delete_entries($arr, array('one.one.two', 'one.two.one'));
}
var_export($array);
输出如您所愿,但太长无法在此处重现。参见 demo on 3v4l.org
更新
上面的代码不会删除顶层的条目,因为数组结构与数组中的低层不同。这可以在外部 foreach
循环中处理:
$excluded = array('two', 'one.one.two', 'one.two.one');
foreach ($array as $key => &$arr) {
if (in_array($arr['website']['id'], $excluded)) {
unset($array[$key]);
}
else {
delete_entries($arr, $excluded);
}
}
我有一个像这样的四层嵌套数组:
$array = [
[
'website' => [
'id' => 'one'
],
'children' => [
[
'website' => [
'id' => 'one.one'
],
'children' => [
[
'website' => [
'id' => 'one.one.one'
],
'children' => [
[
'website' => [
'id' => 'one.one.one.one'
],
'children' => []
],
[
'website' => [
'id' => 'one.one.one.two'
],
'children' => []
]
]
],
[
'website' => [
'id' => 'one.one.two'
],
'children' => [
[
'website' => [
'id' => 'one.one.two.one'
],
'children' => []
],
[
'website' => [
'id' => 'one.one.two.two'
],
'children' => []
]
]
]
]
],
[
'website' => [
'id' => 'one.two'
],
'children' => [
[
'website' => [
'id' => 'one.two.one'
],
'children' => [
[
'website' => [
'id' => 'one.two.one.one'
],
'children' => []
],
[
'website' => [
'id' => 'one.two.one.two'
],
'children' => []
]
]
],
[
'website' => [
'id' => 'one.two.two'
],
'children' => [
[
'website' => [
'id' => 'one.two.two.one'
],
'children' => []
],
[
'website' => [
'id' => 'one.two.two.two'
],
'children' => []
]
]
]
]
]
]
]
];
现在,我想根据一些规则删除一些数组元素。为简单起见,假设我们要删除 'id' 等于 one.one.two
或 one.two.one
.
我正在研究 Whosebug 上提供的一些答案,并试图应用它们来解决我的问题,但没有做太多。最棘手的事情是取消数组中不是数组中最远点的部分。
我正在尝试这样做以记录我想在哪个级别删除数组,然后尝试使用这些数组索引取消设置它们。
$pointer = [];
foreach($array as $key => $level1) {
$level1pointer = $key;
$pointer[] = markToDelete($level1, $level1pointer);
foreach($level1['children'] as $key => $level2) {
$level2pointer = $key;
$pointer[] = markToDelete($level2, $level1pointer, $level2pointer);
foreach($level2['children'] as $key => $level3) {
$level3pointer = $key;
$pointer[] = markToDelete($level3, $level1pointer, $level2pointer, $level3pointer);
foreach($level3['children'] as $key => $level4) {
$level4pointer = $key;
$pointer[] = markToDelete($level4, $level1pointer, $level2pointer, $level3pointer, $level4pointer);
}
}
}
}
function markToDelete($array, $level1 = null, $level2 = null, $level3 = null, $level4 = null) {
$exclusionList = [
'one.one.two',
'one.two.one'
];
if (!empty($array['website']) && in_array($array['website']['id'], $exclusionList)) {
print_r('marking for deletion: '. $array['website']['id'] . PHP_EOL);
return [
'id' => $array['website']['id'],
'level1' => $level1,
'level2' => $level2,
'level3' => $level3,
'level4' => $level4
];
}
return [];
}
我也试过这样使用迭代器:
$it = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($array), \RecursiveIteratorIterator::LEAVES_ONLY);
$newArray = [];
foreach($it as $key => $value) {
$exclusionList = [
'one.one.two',
'one.two.one'
];
if(!in_array($value, $exclusionList)) {
print_r(sprintf('value: %s is ready to be deleted', $value).PHP_EOL);
$newArray[] = $value;
}
}
但是我需要一种方法在遍历迭代器时取消设置数组。
我想要这样的输出:
$array = [
[
'website' => [
'id' => 'one'
],
'children' => [
[
'website' => [
'id' => 'one.one'
],
'children' => [
[
'website' => [
'id' => 'one.one.one'
],
'children' => [
[
'website' => [
'id' => 'one.one.one.one'
],
'children' => []
],
[
'website' => [
'id' => 'one.one.one.two'
],
'children' => []
]
]
],
]
],
[
'website' => [
'id' => 'one.two'
],
'children' => [
[
'website' => [
'id' => 'one.two.two'
],
'children' => [
[
'website' => [
'id' => 'one.two.two.one'
],
'children' => []
],
[
'website' => [
'id' => 'one.two.two.two'
],
'children' => []
]
]
]
]
]
]
]
];
如果能帮助我更有效地解决此问题,我将不胜感激。谢谢。
这是一个递归函数,可以执行您想要的操作。它遍历数组,寻找其网站 ID 在要删除的 ID 列表中的子项并取消设置它们。请注意,由于您有额外的 top-level 数组,您需要在这些值上迭代函数。
function delete_entries(&$array, $ids_to_delete) {
foreach ($array['children'] as $index => &$child) {
if (in_array($child['website']['id'], $ids_to_delete)) {
unset($array['children'][$index]);
}
delete_entries($child, $ids_to_delete);
}
}
foreach ($array as &$arr) {
delete_entries($arr, array('one.one.two', 'one.two.one'));
}
var_export($array);
输出如您所愿,但太长无法在此处重现。参见 demo on 3v4l.org
更新
上面的代码不会删除顶层的条目,因为数组结构与数组中的低层不同。这可以在外部 foreach
循环中处理:
$excluded = array('two', 'one.one.two', 'one.two.one');
foreach ($array as $key => &$arr) {
if (in_array($arr['website']['id'], $excluded)) {
unset($array[$key]);
}
else {
delete_entries($arr, $excluded);
}
}