【问题标题】:array_unique vs array_fliparray_unique 与 array_flip
【发布时间】:2011-11-30 05:40:34
【问题描述】:

如果我有一个有符号整数数组,例如:

Array
(
    [0] => -3
    [1] => 1
    [2] => 2
    [3] => 3
    [4] => 3
)

为了获得独特的价值,我会本能地使用array_unique,但经过考虑,我可以执行两次array_flip,这会产生相同的效果,我认为它会更快吗?

array_unique O(n log n) 因为它使用了排序操作

array_flip O(n)

我的假设是否正确?

更新/示例:

$intArray1 = array(-4,1,2,3);
print_r($intArray1);
$intArray1 = array_flip($intArray1);
print_r($intArray1);
$intArray1 = array_flip($intArray1);
print_r($intArray1);

Array
(
    [0] => -3
    [1] => 1
    [2] => 2
    [3] => 3
    [4] => 3
)
Array
(
    [-3] => 0
    [1] => 1
    [2] => 2
    [3] => 4
)
Array
(
    [0] => -3
    [1] => 1
    [2] => 2
    [4] => 3
)

【问题讨论】:

    标签: php big-o array-unique array-flip


    【解决方案1】:

    我为你做了基准测试:CodePad

    你的直觉是正确的!

    $test=array();
    for($run=0; $run<1000; $run++)
    $test[]=rand(0,100);
    
    $time=microtime(true);
    
    for($run=0; $run<100; $run++)
    $out=array_unique($test);
    
    $time=microtime(true)-$time;
    echo 'Array Unique: '.$time."\n";
    
    $time=microtime(true);
    
    for($run=0; $run<100; $run++)
    $out=array_keys(array_flip($test));
    
    $time=microtime(true)-$time;
    echo 'Keys Flip: '.$time."\n";
    
    $time=microtime(true);
    
    for($run=0; $run<100; $run++)
    $out=array_flip(array_flip($test));
    
    $time=microtime(true)-$time;
    echo 'Flip Flip: '.$time."\n";
    

    输出:

    Array Unique: 1.1829199790955
    Keys Flip: 0.0084578990936279
    Flip Flip: 0.0083951950073242
    

    请注意,array_keys(array_flip($array)) 将按顺序给出一个新的键值,这在许多情况下可能是您想要的(与array_values(array_unique($array)) 相同,但速度更快),而array_flip(array_flip($array)) 与@ 相同(但速度更快) 987654328@,其中的键保持不变。

    【讨论】:

    • 还有array_keys(array_count_values($array)) - 见CodePad
    • @Leith, array_keys(array_count_values( 永远不会比 array_keys(array_flip( 快,但结果总是一样的。
    • @Alasdair,你为什么这么说?我在之前的评论中链接的修改后的 CodePad 基准测试表明有了显着的改进。
    • @Leith,是的,你是对的。你的基准确实说它更快。这很有趣。
    • array_flip O(n) 还是更好?
    【解决方案2】:

    注意:此技术不是 array_unique() 的直接替代品。它仅适用于具有有效键值的数组。 (例如:字符串、整数,可以将事物转换为 int)。当然也不适用于对象数组。

    $input = [true, false, 1, 0, 1.2, "1", "two", "0"];
    var_export(array_unique($input));
    array (
      0 => true,
      1 => false,
      3 => 0,
      4 => 1.2,
      6 => 'two',
    )
    

    对比:

    var_export(array_keys(array_flip($input)));
    
    PHP Warning:  array_flip(): Can only flip STRING and INTEGER values! 
    in php shell code on line 1
    
    array (
      0 => 1,
      1 => 0,
      2 => 'two',
    )
    

    【讨论】:

    • 这不是一个真正的答案,但为我节省了一些时间,非常感谢!
    【解决方案3】:

    没有什么比运行自己的基准测试更好的了。

    ➜  8321620  cat first.php
    <?php
    
    $arr = array(-3, 1, 2, 3, 3);
    
    for($i = 0; $i <= 1000000; $i++) {
        array_unique($arr);
    }
    ➜  8321620  time php first.php
    php first.php  3.24s user 0.01s system 99% cpu 3.251 total
    ➜  8321620  cat second.php
    <?php
    
    $arr = array(-3, 1, 2, 3, 3);
    
    for($i = 0; $i <= 1000000; $i++) {
        array_flip(array_flip($arr));
    }
    ➜  8321620  time php second.php
    php second.php  1.50s user 0.01s system 99% cpu 1.514 total
    

    更新:包含 1000 个元素的数组。

    ➜  8321620  cat first.php
    <?php
    
    $arr = array();
    for($i = 0; $i <= 1000; $i++) {
        $arr[] = rand(0, 1000);
    }
    
    for($i = 0; $i <= 10000; $i++) {
        array_unique($arr);
    }
    ➜  8321620  time php first.php
    php first.php  27.50s user 0.03s system 99% cpu 27.534 total
    ➜  8321620  cat second.php
    <?php
    
    $arr = array();
    for($i = 0; $i <= 1000; $i++) {
        $arr[] = rand(0, 1000);
    }
    
    for($i = 0; $i <= 10000; $i++) {
        array_flip(array_flip($arr));
    }
    ➜  8321620  time php second.php 
    php second.php  1.59s user 0.01s system 99% cpu 1.604 total
    

    所以是的,你的假设是正确的。

    【讨论】:

      【解决方案4】:

      你必须使用

      array_keys( array_flip( $array ) );
      

      这需要更多时间

      我会选择array_unique。它具有解释发生了什么的额外好处。

      【讨论】:

      • array_keys 不也是O(n)吗?
      • 我的意思是你必须使用 2 个函数,而不是 1 个。这将花费更多时间并且还会混淆代码。
      • 我已经给出了我的 array_flip 代码的示例,array_keys 不是必需的
      • 好吧,现在你使用了两次array_flip
      • @Galen,两次 O(n) 比一次 O(n log n) 快得多。
      猜你喜欢
      • 1970-01-01
      • 2021-02-25
      • 2011-06-07
      • 1970-01-01
      • 1970-01-01
      • 2011-01-26
      • 2013-11-27
      相关资源
      最近更新 更多