【问题标题】:subnumeric search on integer array [duplicate]整数数组的子数字搜索[重复]
【发布时间】:2019-05-08 07:16:49
【问题描述】:

我在php中有一个带有数字的数组,例如

$data=array(1500,1515,1300,1466,15,151)

我想在该数组中找到包含 15 的数字,在本例中为

$result=array(1500,1515,15,151).

我知道我可以将它们转换为字符串并使用 strpos 进行搜索,但我想要一种使用整数除法/乘法的更快方法。

有什么建议吗?

接受答案后更新。

使用此代码,我已经测试了方法、字符串和整数,在 1 到 6 位的数字中进行了 10000 次搜索。更快的方法是字符串方法。

<?php
    $data = array();
    for($i=0;$i<10000;$i++)
        $data[]=rand(0,100000);

    $start1 = microtime(true);
    for($i=0;$i<100;$i++)
        foreach($data as $j=>$v)
        {
            $needle = false;
            while($v && !$needle) {
                if($v%100 == 15) // Check if last two digits are 15.
                    $needle = true;
                $v = floor($v/10); // Remove last digit.
            }
        }
    $end1 = microtime(true);

    $start2 = microtime(true);
    for($i=0;$i<100;$i++)
        foreach($data as $j=>$v)
            $needle=strpos($v, '15') !== false;
    $end2 = microtime(true);

    echo "int: ".($end1-$start1)."<br>string: ".($end2-$start2);
?>

输出是:

int: 1.2258439064026
string: 0.4002320766449

【问题讨论】:

  • 到目前为止你有没有尝试过?您有什么理由认为使用数字会更快?
  • 我有疑问,这就是我问的原因,我的数组中有很多数字,我正在尝试优化速度
  • 考虑到您必须反复除以 10 并取模 100 才能找到 15,我认为 strpos 几乎肯定会更快。
  • 这似乎是一项奇怪的任务。它到底有什么用?还是只是一个编码挑战?
  • 因此字符串的速度提高了 3 倍以上。很高兴你的直觉得到证实。查看结果很有趣(并且有用),感谢您发布它们。

标签: php arrays numbers


【解决方案1】:

保持数学函数,没有字符串:

<?php
$data = array(1500,1515,1300,1466,15,151);

$filtered = array_filter($data,
    function($i)
    {
        $needle = false;
        while($i && !$needle) {
            if($i%100 == 15) // Check if last two digits are 15.
                $needle = true;
            $i = floor($i/10); // Remove last digit.
        }

        return $needle;
    }
);

var_dump($filtered);

输出:

array(4) {
  [0]=>
  int(1500)
  [1]=>
  int(1515)
  [4]=>
  int(15)
  [5]=>
  int(151)
}

这是受尼克评论的启发。 15 检查接受一个数字,检查它是否以 15 结尾,如果不是则删除一个数字,依此类推。

【讨论】:

  • 这个解决方案看起来很酷,它专门用于 15 或 2 位数字(%100 操作),但可以轻松更改为遗传。我会接受这个作为解决方案,我会用一些数字进行测试,看看它是否是更快的方法。
  • @hamboy75 是的,确实会返回比较每个结果的结果。您可能希望在执行过程中进行循环和过滤,而不是使用 array_filter。
【解决方案2】:

Php 会在你执行时强制转换为字符串:

<?php

$data = array(1500,1515,1300,1466,15,151);

$filtered = array_filter($data, function($n) {
    return strpos($n, '15') !== false;
});

var_dump($filtered);

输出:

array(4) {
  [0]=>
  int(1500)
  [1]=>
  int(1515)
  [4]=>
  int(15)
  [5]=>
  int(151)
}

但如果将数组加载到内存中是个问题,我会考虑将任务分块。

【讨论】:

  • 我认为 OP 知道这个选项,但正在寻找数学方法(我也相信使用 strpos 是更好的方法......)
  • 我只提到它,因为听起来好像 OP 可能正在考虑做类似的事情:array_map('strval', $data) first.
  • array_filter 带有匿名函数,还是循环和过滤以获得性能?
  • 我确实认为你的方式更好(赞成) - 但遗憾的是不是 OP 想要的
猜你喜欢
  • 2014-01-06
  • 1970-01-01
  • 2013-03-10
  • 1970-01-01
  • 1970-01-01
  • 2018-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多