合并 PHP 中的 2 个数组,仅保留第一个数组中的键
Merge 2 arrays in PHP, keeping only keys from first array
我有这两个数组:
$list = [
'fruit' => [],
'animals' => [],
'objects' => [],
];
$dataArray = [
'fruit' => 'apple',
'animals' => ['dog', 'cat'],
'asd' => 'bla'
];
我想合并它们,使末尾的 $list 为:
[fruit] => Array
(
[0] => apple
)
[animals] => Array
(
[0] => dog
[1] => cat
)
[objects] => Array
(
)
所以,注意事项:
- 即使 'fruit' 只有一个元素,在 $list
中仍然是一个数组
- $list 中缺少的键('asd' 键)被忽略
- 没有值的键仍然保留,即使是空的
使用 array_merge 无效:
$merged = array_merge($list, $dataArray);
[fruit] => apple
[animals] => Array
(
[0] => dog
[1] => cat
)
[objects] => Array
(
)
[asd] => bla
我设法得到了我想要的:
foreach ($dataArray as $key => $value) {
if (isset($list[$key])) {
if (is_array($value)) {
$list[$key] = $value;
}
else {
$list[$key] = [$value];
}
}
}
但我想知道是否有更简洁的方法或其他一些我不知道的 php 功能。
您可以通过几个步骤实现此目的:
$result = array_intersect_key($dataArray, $list);
这将为您 return 一个包含第一个数组中所有元素的数组,然后过滤第二个数组中的键。这给你:
Array
(
[fruit] => apple
[animals] => Array
(
[0] => dog
[1] => cat
)
)
然后您可以重新添加第一个数组中缺少的键,使用:
$result + $list;
+
运算符和 array_merge
之间的区别在于前者不会使用第二个数组的值覆盖第一个数组。它只会添加任何缺失的元素。
在一行中,结果为:
$result = array_intersect_key($dataArray, $list) + $list;
您可以在此处查看实际效果:https://eval.in/865733
编辑: 抱歉,完全错过了将元素保留为数组的部分。如果它们总是数组,那么您可以添加一个快速的单行代码,例如:
$result = array_map(function ($e) { return (array) $e; }, $result);
这会将所有顶级元素转换为数组。如果您的逻辑比这更复杂,那么我不确定您是否会找到一种方法来使用内置函数,抱歉。
第二条规则(“2. $list
中缺少的键('asd'
键)被简单地忽略了”)告诉我迭代 $list
,没有超过 $dataArray
。如果 $dataArray
比 $list
大得多,迭代它是浪费时间,因为它的大部分元素都被忽略了。
你的规则没有解释如何处理 $list
的元素,当它们不为空时(我假设它们总是数组,否则游戏会改变并且提供通用代码变得太复杂了处理它)。
我建议的代码如下所示:
// Build the result in $result
// (you can modify $list as well if you prefer it that way)
$result = array();
// 2. keys missing from $list ('asd' key) are simply ignored
// iterate over the keys of $list, handle only the keys present in $dataArray
foreach ($list as $key => $value) {
if (array_key_exists($dataArray, $key)) {
// $key is present in $dataArray, use the value from $dataArray
$value = $dataArray[$key];
// 1. even if 'fruit' had only one element, is still an array in $list
if (! is_array($value)) {
$value = array($value);
}
}
// 3. keys with no values are still kept, even if empty
// if the key is not present in $dataArray, its value from $list is used
$result[$key] = $value;
}
如果将 if (! is_array($value))
块移到 if (array_key_exists())
块之外,它也会将 $list
的值转换为数组,这些值不是数组并且与不存在的键相关联在 $dataArray
中(例如 $list['objects']
)。这样,代码运行后,$result
的所有值都是数组。
你的代码也不错。除了遍历 $list
而不是遍历 $dataArray
之外,没有办法让它更快或更容易以惊人的方式阅读。我在这里建议的代码只是编写相同内容的另一种方式。
我的方法将执行 3 个非常简单的操作:
- 运行 单个循环,同时使用
&$v
. 通过引用修改 $list
- 忽略在
$dataArray
中找不到匹配键的迭代。
- 将
$dataArray
中的每个合格值强制转换为数组并覆盖初始的空子数组。
如果限定值不是数组,它将成为生成的子数组中的唯一元素;如果是,则子数组没有任何变化。
代码:(Demo)
$list = [
'fruit' => [],
'animals' => [],
'objects' => []
];
$dataArray = [
'fruit' => 'apple',
'animals' => ['dog', 'cat'],
'asd' => 'bla'
];
foreach ($list as $k => &$v) {
if (isset($dataArray[$k])) {
$v = (array)$dataArray[$k];
}
}
var_export($list);
输出:
array (
'fruit' =>
array (
0 => 'apple',
),
'animals' =>
array (
0 => 'dog',
1 => 'cat',
),
'objects' =>
array (
),
)
这是两行解决方案(但你可以简单地把它变成一行:))
$list = [
'fruit' => [],
'animals' => [],
'objects' => [],
];
$dataArray = [
'fruit' => 'apple',
'animals' => ['dog', 'cat'],
'asd' => 'bla'
];
$list = array_merge($list, array_intersect_key($dataArray, $list));
array_walk($list, function(&$item){$item = (array)$item;});
我有这两个数组:
$list = [
'fruit' => [],
'animals' => [],
'objects' => [],
];
$dataArray = [
'fruit' => 'apple',
'animals' => ['dog', 'cat'],
'asd' => 'bla'
];
我想合并它们,使末尾的 $list 为:
[fruit] => Array
(
[0] => apple
)
[animals] => Array
(
[0] => dog
[1] => cat
)
[objects] => Array
(
)
所以,注意事项:
- 即使 'fruit' 只有一个元素,在 $list 中仍然是一个数组
- $list 中缺少的键('asd' 键)被忽略
- 没有值的键仍然保留,即使是空的
使用 array_merge 无效:
$merged = array_merge($list, $dataArray);
[fruit] => apple
[animals] => Array
(
[0] => dog
[1] => cat
)
[objects] => Array
(
)
[asd] => bla
我设法得到了我想要的:
foreach ($dataArray as $key => $value) {
if (isset($list[$key])) {
if (is_array($value)) {
$list[$key] = $value;
}
else {
$list[$key] = [$value];
}
}
}
但我想知道是否有更简洁的方法或其他一些我不知道的 php 功能。
您可以通过几个步骤实现此目的:
$result = array_intersect_key($dataArray, $list);
这将为您 return 一个包含第一个数组中所有元素的数组,然后过滤第二个数组中的键。这给你:
Array
(
[fruit] => apple
[animals] => Array
(
[0] => dog
[1] => cat
)
)
然后您可以重新添加第一个数组中缺少的键,使用:
$result + $list;
+
运算符和 array_merge
之间的区别在于前者不会使用第二个数组的值覆盖第一个数组。它只会添加任何缺失的元素。
在一行中,结果为:
$result = array_intersect_key($dataArray, $list) + $list;
您可以在此处查看实际效果:https://eval.in/865733
编辑: 抱歉,完全错过了将元素保留为数组的部分。如果它们总是数组,那么您可以添加一个快速的单行代码,例如:
$result = array_map(function ($e) { return (array) $e; }, $result);
这会将所有顶级元素转换为数组。如果您的逻辑比这更复杂,那么我不确定您是否会找到一种方法来使用内置函数,抱歉。
第二条规则(“2. $list
中缺少的键('asd'
键)被简单地忽略了”)告诉我迭代 $list
,没有超过 $dataArray
。如果 $dataArray
比 $list
大得多,迭代它是浪费时间,因为它的大部分元素都被忽略了。
你的规则没有解释如何处理 $list
的元素,当它们不为空时(我假设它们总是数组,否则游戏会改变并且提供通用代码变得太复杂了处理它)。
我建议的代码如下所示:
// Build the result in $result
// (you can modify $list as well if you prefer it that way)
$result = array();
// 2. keys missing from $list ('asd' key) are simply ignored
// iterate over the keys of $list, handle only the keys present in $dataArray
foreach ($list as $key => $value) {
if (array_key_exists($dataArray, $key)) {
// $key is present in $dataArray, use the value from $dataArray
$value = $dataArray[$key];
// 1. even if 'fruit' had only one element, is still an array in $list
if (! is_array($value)) {
$value = array($value);
}
}
// 3. keys with no values are still kept, even if empty
// if the key is not present in $dataArray, its value from $list is used
$result[$key] = $value;
}
如果将 if (! is_array($value))
块移到 if (array_key_exists())
块之外,它也会将 $list
的值转换为数组,这些值不是数组并且与不存在的键相关联在 $dataArray
中(例如 $list['objects']
)。这样,代码运行后,$result
的所有值都是数组。
你的代码也不错。除了遍历 $list
而不是遍历 $dataArray
之外,没有办法让它更快或更容易以惊人的方式阅读。我在这里建议的代码只是编写相同内容的另一种方式。
我的方法将执行 3 个非常简单的操作:
- 运行 单个循环,同时使用
&$v
. 通过引用修改 - 忽略在
$dataArray
中找不到匹配键的迭代。 - 将
$dataArray
中的每个合格值强制转换为数组并覆盖初始的空子数组。 如果限定值不是数组,它将成为生成的子数组中的唯一元素;如果是,则子数组没有任何变化。
$list
代码:(Demo)
$list = [
'fruit' => [],
'animals' => [],
'objects' => []
];
$dataArray = [
'fruit' => 'apple',
'animals' => ['dog', 'cat'],
'asd' => 'bla'
];
foreach ($list as $k => &$v) {
if (isset($dataArray[$k])) {
$v = (array)$dataArray[$k];
}
}
var_export($list);
输出:
array (
'fruit' =>
array (
0 => 'apple',
),
'animals' =>
array (
0 => 'dog',
1 => 'cat',
),
'objects' =>
array (
),
)
这是两行解决方案(但你可以简单地把它变成一行:))
$list = [
'fruit' => [],
'animals' => [],
'objects' => [],
];
$dataArray = [
'fruit' => 'apple',
'animals' => ['dog', 'cat'],
'asd' => 'bla'
];
$list = array_merge($list, array_intersect_key($dataArray, $list));
array_walk($list, function(&$item){$item = (array)$item;});