【问题标题】:Trying to understand array_uintersect behavior试图理解 array_uintersect 行为
【发布时间】:2015-03-05 02:58:21
【问题描述】:

让我们继续。为什么array_uintersectsorting 之后的第一个数组中没有compare values?我的拙见array_udiffarray_uintersect 应该有类似的算法,但他们没有。为什么?

$compare = function($a, $b) use(&$iteration_count)
    {
    echo("$a : $b\n");
    $iteration_count++;
    return strcmp($a, $b);
    };

$a = array('a', 'b', 'c');
$b = array('x', 'y', 'z');

$iteration_count = 0;
echo "array_udiff:" . json_encode(array_udiff($a, $b, $compare)) . "\n";
echo "iterations: $iteration_count\n\n";

$iteration_count = 0;
echo "array_uintersect:" . json_encode(array_uintersect($a, $b, $compare)) . "\n";
echo "iterations: $iteration_count\n\n";

输出

b : a
c : b
y : x
z : y
a : x
a : b
b : x
b : c
c : x
array_udiff:["a","b","c"]
iterations: 9

b : a
c : b
y : x
z : y
a : x  // comparison started
b : x  // but there is no comparison to skip values
c : x
array_uintersect:[]
iterations: 7

【问题讨论】:

    标签: php arrays sorting


    【解决方案1】:

    array_intersect() 和朋友采用的算法是首先假设第一个数组的所有值都存在于其他数组中;在迭代过程中,它将删除未通过此断言的元素。

    当在其他数组之一中找不到元素时,实现可以做两件事:

    1. 将下一个元素与当前元素进行比较,并在它们相等时从最终结果中删除(这就是 diff 所做的)
    2. 将下一个元素与其他数组的最后一个检查元素进行比较,并不断将其从最终结果中删除,直到它更大(或到达数组末尾)。

    对于 PHP,选择后者。这有一点优势,因为它可以跳过大于当前元素但小于其他数组的最后一个检查元素的值。例如:

    $a = ['a.a0', 'a.a1', 'b.a2', 'c.a3'];
    $b = ['a.c0', 'd.c1'];
    
    function cmp_val($a, $b)
    {
        echo "$a <=> $b\n";
        return strcmp($a[0], $b[0]);
    }
    
    print_r(array_uintersect($a, $b, 'cmp_val'));
    

    输出:

    ...
    -- intersect starts
    a.a0 <=> a.c0
    a.a0 <=> a.a1 <-- match
    a.a1 <=> b.a2
    b.a2 <=> d.c1 <-- no match
    c.a3 <=> d.c1
    

    正如你所见,如果一个值出现在所有其他数组中,它使用在第一个数组中进行比较的策略,就像 diff 一样;如果该值不存在于任何其他数组中,则使用其他策略。

    【讨论】:

      【解决方案2】:

      每个数组的初始排序时间为 O(n log(n)),因此优化后续的 O(n) 消除过程几乎没有收益。

      这在 3 元素数组上可能会更慢,但对于更大的尺寸会变得可以忽略不计。

      【讨论】:

        【解决方案3】:

        我是对的,也是错的。这些函数具有相似的算法。

        $compare = function($a, $b) use(&$iteration_count)
            {
            echo("$a : $b\n");
            $iteration_count++;
            return strcmp($a[0], $b[0]);
            };
        
        $a = array('a1', 'b1', 'c1');
        $b = array('a2', 'b2', 'c2');
        
        $iteration_count = 0;
        echo "array_uintersect:" . json_encode(array_uintersect($a, $b, $compare)) . "\n";
        echo "iterations: $iteration_count\n\n";
        

        输出

        b1 : a1 
        c1 : b1
        b2 : a2
        c2 : b2
        a1 : a2  // comparison started
        a1 : b1  // it trying to skip values after it have been matched
        b1 : b2
        b1 : c1
        c1 : c2
        array_uintersect:["a1","b1","c1"]
        iterations: 9
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-02-18
          • 2023-03-17
          • 1970-01-01
          • 1970-01-01
          • 2011-05-17
          • 2020-12-19
          相关资源
          最近更新 更多