合并两个平面数组,并在另一个数组多次出现相同值时省略其中一个数组中的值


Merge two flat arrays and omit values from one array when the other array has more occurrences of the same value

我想合并两个数组的每个元素,但如果两个数组中都有一个值,那么只添加该元素量最大的数组中的值。结果数组不需要以任何特殊的方式进行排序,但为了可读性,我在这里进行了排序。

样本输入:

$array1 = [1, 4, 7, 3, 3, 3];
$array2 = [4, 0, 3, 4, 9, 9];

期望结果:

 [0, 1, 3, 3, 3, 4, 4, 7, 9, 9]
//a2 a1 a1 a1 a1 a2 a2 a1 a2 a2

注意,这将用于具有未知整数值的大数组。有没有一种不需要太多时间/处理能力的好方法可以做到这一点?

试试这个:

<?php
$array1 = [1, 4, 7, 3, 3, 3];
$array2 = [4, 0, 3, 4, 9, 9];
function min_merge($arr1, $arr2) {
    $arr1 = array_count_values($arr1);
    $arr2 = array_count_values($arr2);
    foreach ($arr2 as $index => $arr)
        if (!isset($arr1[$index]) || $arr > $arr1[$index])
            $arr1[$index] = $arr;
    foreach ($arr1 as $index => $arr)
        for ($i = 0; $i < $arr; $i++)
            $final[] = $index;
    return $final;
}
print_r(min_merge($array1, $array2));

输出:

Array (
    [0] => 1
    [1] => 4
    [2] => 4
    [3] => 7
    [4] => 3
    [5] => 3
    [6] => 3
    [7] => 0
    [8] => 9
    [9] => 9 
)

未排序,但它包含[0, 1, 3, 3, 3, 4, 4, 7, 9, 9]中的所有数字。

$count[0] = array_count_values($arr1);
$count[1] = array_count_values($arr2);
$out = array();
array_map(function($e) use(&$out, $count){
    $n1 = (isset($count[0][$e])) ? $count[0][$e] : 0;
    $n2 = (isset($count[1][$e])) ? $count[1][$e] : 0;
    $next = ($n2 > $n1) ? array_fill(0, $n2, $e) : array_fill(0, $n1, $e);
    $out = array_merge($out, $next);
}, array_keys($count[0] + $count[1]));
print_r($out);
  1. 我使用PSR-12编码标准对@DaveChen的答案进行了现代化的重写,并消除了一次性声明。这种方法使用一个循环来确定两个值计数数组共享的数字的较大计数,然后使用第二个循环来填充结果数组。(演示)

    $counts1 = array_count_values($array1);
    foreach (array_count_values($array2) as $number => $count) {
        if ($count > ($counts1[$number] ?? 0)) {
            $counts1[$number] = $count;
        }
    }
    $result = [];
    foreach ($counts1 as $number => $count) {
        array_push($result, ...array_fill(0, $count, $number));
    }
    var_export($result);
    
  2. 我对@Expedito的答案进行了现代化的重写,它不滥用array_map()(当不使用array_map()的返回值时,请使用array_walk()进行函数式编程),使用foreach()循环来消除变量范围问题,并且通常实现D.R.Y.技术。(演示)

    $counts1 = array_count_values($array1);
    $counts2 = array_count_values($array2);
    $result = [];
    foreach ($counts1 + $counts2 as $num => $cnt) { 
        array_push(
            $result,
            ...array_fill(
                0,
                max($counts1[$num] ?? 0, $counts2[$num] ?? 0),
                $num
            )
        );    
    }
    var_export($result);
    
  3. 我想添加一种我自己的新方法,尽管它可能比其他两个片段更好,也可能不更好。脚本对第一个值计数数组进行一次遍历,以填充一个临时数组,该数组要求在结果数组中表示第一个数组中的哪些数字。然后,它将值交集与第一个数组隔离开来,将值差与第二个数组隔离出来,然后合并它们。(演示)

    $counts1 = array_count_values($array1);
    $counts2 = array_count_values($array2);
    $keepFrom1 = array_keys(
        array_filter(
            $counts1,
            fn($count, $number) => ($counts2[$number] ?? 0) <= $count,
            ARRAY_FILTER_USE_BOTH
        )
    );
    var_export(
        array_merge(
            array_intersect($array1, $keepFrom1),
            array_diff($array2, $keepFrom1)
        )
    );
    

可能不是最优化的,但

<?php
$one=[1, 4, 7, 3, 3, 3];
$two=[4, 0, 3, 4, 9, 9];
sort($one);
sort($two);
foreach($one as $el)
{
$combined[]=$el;
if (array_search($el,$two))
{
unset($two[array_search($el,$two)]);
}
}
foreach($two as $el)
{
$combined[]=$el;
}
sort($combined);
print_r($combined);
?>