11

我正在使用array_diff() 从array1 中取出在array2 中找到的值。问题是它会从 array1 中删除所有出现的事件,正如 PHP 文档所指出的那样。我希望它一次只取出一个。

$array1 = array();
$array1[] = 'a';
$array1[] = 'b';
$array1[] = 'a';

$array2 = array();
$array2[] = 'a';

它应该返回一个包含一个“a”和一个“b”的数组,而不是一个只有“b”的数组;

4

2 回答 2

12

只是为了好玩,刚刚想到的东西。只要您的数组包含字符串就可以工作:

$a = array('a','b','a','c');
$b = array('a');

$counts = array_count_values($b);
$a = array_filter($a, function($o) use (&$counts) {
    return empty($counts[$o]) || !$counts[$o]--;
});

它的优点是它只遍历每个阵列一次。

看到它在行动

这个怎么运作:

首先计算第二个数组中每个元素的频率。这给了我们一个数组,其中键是应该从中删除的元素,$a值是应该删除每个元素的次数。

然后array_filter用于$a逐个检查元素并删除应该删除的元素。如果没有与正在检查的项目相等的键或该项目的剩余删除计数已达到零,则过滤器函数用于empty返回;的行为完全符合要求。trueempty

如果以上都不成立,那么我们要返回false并将删除计数减一。false || !$counts[$o]--为了简洁,使用是一个技巧:它会减少计数并始终评估为,false因为我们知道计数一开始就大于零(如果不是,||则会在评估后短路empty)。

于 2013-06-06T22:51:31.570 回答
6

编写一些函数,从第一个数组中逐个删除元素,例如:

function array_diff_once($array1, $array2) {
    foreach($array2 as $a) {
        $pos = array_search($a, $array1);
        if($pos !== false) {
            unset($array1[$pos]);
        }
    }

    return $array1;
}

$a = array('a', 'b', 'a', 'c', 'a', 'b');
$b = array('a', 'b', 'c');

print_r( array_diff_once($a, $b) );
于 2013-06-06T22:46:17.453 回答