PHP二维数组过滤合并:保留原数组中仅出现一次的Email并合并键
PHP二维数组筛选与键合并解决方案
需求说明
从两个PHP二维数组中筛选出email值在任一原数组中仅出现一次的元素,并将相同email对应的元素键值合并,得到目标数组。
现有数组
$arr1 = [ ['email' => 'aa@gmail.com', 'name' => 'John Doe'], ['email' => 'bb@gmail.com', 'name' => 'Johnny Sins'], ['email' => 'cc@gmail.com', 'name' => 'Jose Alvarado'] ]; $arr2 = [ ['email' => 'cc@gmail.com', 'country' => 'Japan'], ['email' => 'cc@gmail.com', 'country' => 'China'], ['email' => 'bb@gmail.com', 'country' => 'Korea'], ];
期望结果
[ ['email' => 'aa@gmail.com', 'name' => 'John Doe'], ['email' => 'bb@gmail.com', 'name' => 'Johnny Sins', 'country' => 'Korea'], ];
现有代码问题
你当前的代码仅完成了数组合并和简单过滤,既没处理键值合并,过滤逻辑也不准确——用合并后的数组统计次数,没有区分原数组的出现情况:
$merged = array_merge($arr1, $arr2); $result = array_filter($merged, function($value) use($merged) { return array_count_values(array_column($merged, 'email'))[$value['email']] < 3; });
解决方案
步骤1:统计原数组中email的出现次数
分别统计两个原数组中每个email的出现次数,筛选出在两个原数组中出现次数都不超过1次的email:
// 统计$arr1中各email的出现次数 $counts1 = array_count_values(array_column($arr1, 'email')); // 统计$arr2中各email的出现次数 $counts2 = array_count_values(array_column($arr2, 'email')); // 筛选符合条件的email:在两个原数组中出现次数均≤1 $validEmails = array_filter( array_unique(array_merge(array_keys($counts1), array_keys($counts2))), function($email) use($counts1, $counts2) { return ($counts1[$email] ?? 0) <= 1 && ($counts2[$email] ?? 0) <= 1; } );
步骤2:合并相同email的键值
遍历两个数组,将相同email的元素键值合并,仅保留符合条件的条目:
$result = []; // 先处理$arr1的有效元素 foreach ($arr1 as $item) { $email = $item['email']; if (in_array($email, $validEmails)) { $result[$email] = $item; } } // 再处理$arr2的元素,合并到对应email的条目中 foreach ($arr2 as $item) { $email = $item['email']; if (in_array($email, $validEmails)) { $result[$email] = array_merge($result[$email] ?? [], $item); } } // 重置数组索引(按需选择,若需要连续数字索引则执行) $result = array_values($result);
完整可运行代码
$arr1 = [ ['email' => 'aa@gmail.com', 'name' => 'John Doe'], ['email' => 'bb@gmail.com', 'name' => 'Johnny Sins'], ['email' => 'cc@gmail.com', 'name' => 'Jose Alvarado'] ]; $arr2 = [ ['email' => 'cc@gmail.com', 'country' => 'Japan'], ['email' => 'cc@gmail.com', 'country' => 'China'], ['email' => 'bb@gmail.com', 'country' => 'Korea'], ]; // 统计两个原数组的email出现次数 $counts1 = array_count_values(array_column($arr1, 'email')); $counts2 = array_count_values(array_column($arr2, 'email')); // 筛选有效email $validEmails = array_filter( array_unique(array_merge(array_keys($counts1), array_keys($counts2))), function($email) use($counts1, $counts2) { return ($counts1[$email] ?? 0) <= 1 && ($counts2[$email] ?? 0) <= 1; } ); // 合并元素并生成结果 $result = []; foreach ($arr1 as $item) { $email = $item['email']; if (in_array($email, $validEmails)) { $result[$email] = $item; } } foreach ($arr2 as $item) { $email = $item['email']; if (in_array($email, $validEmails)) { $result[$email] = array_merge($result[$email] ?? [], $item); } } $result = array_values($result); // 输出结果 print_r($result);
代码说明
- 统计次数:基于原数组单独统计,确保筛选逻辑符合“email在任一原数组中仅出现一次”的要求,而非合并后的数组。
- 筛选有效email:排除在任一原数组中重复出现的email(比如
cc@gmail.com在$arr2中出现两次,直接被过滤)。 - 合并键值:先将
$arr1的有效元素存入结果,再遍历$arr2合并对应email的键值,最后重置索引得到目标格式。
内容的提问来源于stack exchange,提问作者nwantiti
相关产品推荐
相关产品推荐

