递归迭代多维数组和 return 相同的数组结构并在 PHP 中插入新的 key/values
Iterate multidimensional Array recursively and return same array structure and inserting new key/values in PHP
我正在尝试编写一个片段,它采用多维数组并在找到命名搜索键的同一级别插入一些键。
我不必依赖数组的结构(但最多 5 层)
我不能使用引用传递,所以传统的循环函数对这种方法没有帮助。
我有 2 个选项:SPL 或重新构造数组并沿途更改它的递归
使用 SPL 我似乎无法插入新值..
$a= new \ArrayObject($priceConfig);
$array = new \RecursiveArrayIterator($a);
$iterator = new \RecursiveIteratorIterator($array, \RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $key => $value) {
if (is_array($value) && $key == 'prices') {
$iterator->offsetSet('myPrice',['amount'=>'1.00']);
}
}
print_r($a->getArrayCopy());
它不会在所需级别插入新密钥,但它会循环遍历数组。我错过了什么?
重建数组并在我的嵌套数组中的键搜索中插入新值的递归函数有效,但我想使用迭代器来做到这一点..
function recursive( $input, $searchKey, $key=null) {
$holder = array();
if(is_array( $input)) {
foreach( $input as $key => $el) {
if (is_array($el)) {
$holder[$key] = recursive($el, $searchKey, $key);
if ($key == $searchKey) {
$holder[$key]['inertedPrice'] = "value";
}
} else {
$holder[$key] = $el;
}
}
}
return $holder;
}
INPUT(总会有一些"prices key and structure at X level")
[1] => Array
(
[1] => Array
(
[prices] => Array
(
[onePrice] => Array( [amount] => 10)
[finalPrice] => Array ([amount] => 10)
)
[key1] => value2
[key2] => value2
)
[2] => Array
(
[prices] => Array
(
[otherPrice] => Array([amount] => 20)
[finalPrice] => Array([amount] => 20)
)
[key] => value
)
)
)
输出
[1] => Array
(
[1] => Array
(
[prices] => Array
(
[onePrice] => Array( [amount] => 10)
[finalPrice] => Array ([amount] => 10)
[INSERTEDPrice] => Array([amount] => value)
)
[key1] => value2
[key2] => value2
)
[2] => Array
(
[prices] => Array
(
[otherPrice] => Array([amount] => 20)
[finalPrice] => Array([amount] => 20)
[INSERTEDPrice] => Array([amount] => )
)
[key] => value
)
)
)
您可以通过使用自定义迭代器逻辑扩展 RecursiveArrayIterator
来使用迭代器执行此操作:
class Foo extends RecursiveArrayIterator
{
public function getChildren()
{
if ($this->key() == 'prices') {
return new self(array_merge($this->current(), ['foo' => 'bar']));
} else {
return parent::getChildren();
}
}
}
您可以使用 foreach 循环和递归等基本工具相当轻松地解决问题。这里有这样的解决方案。
function mergeWithKey($targetKey, $new, array $array) {
foreach ($array as $key => $value) {
if ($key === $targetKey) {
$array[$key] = array_merge($array[$key], $new);
}
elseif (is_array($value)) {
$array[$key] = mergeWithKey($targetKey, $new, $value);
}
}
return $array;
}
// Example
$output = mergeWithKey('prices', array('INSERTEDPrice' => 'value'), $input);
简单地说,当我们遍历数组时,如果我们找到我们正在寻找的键,那么我们将合并到新价格中。如果我们找到一个子数组,那么我们将新价格合并到该子数组中。
我努力通过将键 "prices" 作为参数来概括函数。这可能仍然是一个不太可能被重用的不稳定函数。
使用一些常见的算法,您可以很好地启动此功能,好处是您可以重用这些算法。一种是将数组同时映射key和value,另一种是将二维数组扁平化为一维数组
function arrayMapWithKey(callable $f, array $array) {
$out = array();
foreach ($array as $key => $value) {
$out[$key] = $f($key, $value);
}
return $out;
}
function concat(array $array) {
if (empty($array)) {
return array();
}
else {
return call_user_func_array('array_merge', $array);
}
}
这些定义使您能够编写替代解决方案。
function addPrice($name, $price, $data) {
return concat(arrayMapWithKey(
function ($k, $v) use ($name, $price) {
if ($k === 'prices') {
return array($k => array_merge($v, array($name => $price)));
}
elseif (is_array($v)) {
return array($k => addPrice($name, $price, $v));
}
else {
return array($k => $v);
}
},
$data
));
}
arrayMapWithKey
的另一种表述是用值复制键,然后使用常规 array_map
。
function arrayWithKeys(array $array) {
$out = array();
foreach ($array as $key => $value) {
// in PHP arrays are often used as tuples,
// and here we have a 2-tuple.
$out[] = array($key, $value);
}
return $out;
}
我正在尝试编写一个片段,它采用多维数组并在找到命名搜索键的同一级别插入一些键。 我不必依赖数组的结构(但最多 5 层) 我不能使用引用传递,所以传统的循环函数对这种方法没有帮助。
我有 2 个选项:SPL 或重新构造数组并沿途更改它的递归
使用 SPL 我似乎无法插入新值..
$a= new \ArrayObject($priceConfig);
$array = new \RecursiveArrayIterator($a);
$iterator = new \RecursiveIteratorIterator($array, \RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $key => $value) {
if (is_array($value) && $key == 'prices') {
$iterator->offsetSet('myPrice',['amount'=>'1.00']);
}
}
print_r($a->getArrayCopy());
它不会在所需级别插入新密钥,但它会循环遍历数组。我错过了什么?
重建数组并在我的嵌套数组中的键搜索中插入新值的递归函数有效,但我想使用迭代器来做到这一点..
function recursive( $input, $searchKey, $key=null) {
$holder = array();
if(is_array( $input)) {
foreach( $input as $key => $el) {
if (is_array($el)) {
$holder[$key] = recursive($el, $searchKey, $key);
if ($key == $searchKey) {
$holder[$key]['inertedPrice'] = "value";
}
} else {
$holder[$key] = $el;
}
}
}
return $holder;
}
INPUT(总会有一些"prices key and structure at X level")
[1] => Array
(
[1] => Array
(
[prices] => Array
(
[onePrice] => Array( [amount] => 10)
[finalPrice] => Array ([amount] => 10)
)
[key1] => value2
[key2] => value2
)
[2] => Array
(
[prices] => Array
(
[otherPrice] => Array([amount] => 20)
[finalPrice] => Array([amount] => 20)
)
[key] => value
)
)
)
输出
[1] => Array
(
[1] => Array
(
[prices] => Array
(
[onePrice] => Array( [amount] => 10)
[finalPrice] => Array ([amount] => 10)
[INSERTEDPrice] => Array([amount] => value)
)
[key1] => value2
[key2] => value2
)
[2] => Array
(
[prices] => Array
(
[otherPrice] => Array([amount] => 20)
[finalPrice] => Array([amount] => 20)
[INSERTEDPrice] => Array([amount] => )
)
[key] => value
)
)
)
您可以通过使用自定义迭代器逻辑扩展 RecursiveArrayIterator
来使用迭代器执行此操作:
class Foo extends RecursiveArrayIterator
{
public function getChildren()
{
if ($this->key() == 'prices') {
return new self(array_merge($this->current(), ['foo' => 'bar']));
} else {
return parent::getChildren();
}
}
}
您可以使用 foreach 循环和递归等基本工具相当轻松地解决问题。这里有这样的解决方案。
function mergeWithKey($targetKey, $new, array $array) {
foreach ($array as $key => $value) {
if ($key === $targetKey) {
$array[$key] = array_merge($array[$key], $new);
}
elseif (is_array($value)) {
$array[$key] = mergeWithKey($targetKey, $new, $value);
}
}
return $array;
}
// Example
$output = mergeWithKey('prices', array('INSERTEDPrice' => 'value'), $input);
简单地说,当我们遍历数组时,如果我们找到我们正在寻找的键,那么我们将合并到新价格中。如果我们找到一个子数组,那么我们将新价格合并到该子数组中。
我努力通过将键 "prices" 作为参数来概括函数。这可能仍然是一个不太可能被重用的不稳定函数。
使用一些常见的算法,您可以很好地启动此功能,好处是您可以重用这些算法。一种是将数组同时映射key和value,另一种是将二维数组扁平化为一维数组
function arrayMapWithKey(callable $f, array $array) {
$out = array();
foreach ($array as $key => $value) {
$out[$key] = $f($key, $value);
}
return $out;
}
function concat(array $array) {
if (empty($array)) {
return array();
}
else {
return call_user_func_array('array_merge', $array);
}
}
这些定义使您能够编写替代解决方案。
function addPrice($name, $price, $data) {
return concat(arrayMapWithKey(
function ($k, $v) use ($name, $price) {
if ($k === 'prices') {
return array($k => array_merge($v, array($name => $price)));
}
elseif (is_array($v)) {
return array($k => addPrice($name, $price, $v));
}
else {
return array($k => $v);
}
},
$data
));
}
arrayMapWithKey
的另一种表述是用值复制键,然后使用常规 array_map
。
function arrayWithKeys(array $array) {
$out = array();
foreach ($array as $key => $value) {
// in PHP arrays are often used as tuples,
// and here we have a 2-tuple.
$out[] = array($key, $value);
}
return $out;
}