代码之家  ›  专栏  ›  技术社区  ›  vdegenne Kuba Å imonovský

如何在不使用PHP中任何函数的情况下执行此数组过滤?[已关闭]

  •  -4
  • vdegenne Kuba Å imonovský  · 技术社区  · 7 年前

    $a = [1,4,5,8,9,...];
    

    包含大量间断数的井,以及

    $p = [
      1 => [...],
      3 => [...],
      8 => [...],
      10 => [...],
      ...
    ];
    

    包含索引也停止的数组。

    $a $p

    有可能吗?如果是,如何?如果没有,解决这个问题的最佳方法是什么?

    2 回复  |  直到 4 年前
        1
  •  1
  •   rickdenhaan    7 年前

    当然,有可能:

    $filtered_array = [];
    foreach ($a as $index => $value) {
        foreach ($p as $key => $sub_array) {
            if ($key == $value) {
                // this $value of $a corresponds with an existing index in $p, so
                // do NOT add it to our $filtered_array but move on to the next
                // value of $a
                continue 2;
            }
        }
        $filtered_array[$index] = $value;
    }
    

    当然,这将是非常缓慢的,因为对于 $a $p 您需要迭代整个 $p 数组以发现它不在其中。更有效的解决方案是利用PHP的 OutOfBoundsException

    $filtered_array = [];
    foreach ($a as $index => $value) {
        try {
            $p[$value];
        } except (OutOfBoundsException $e) {
            // $value does not exist as an index of $p
            $filtered_array[$index] = $value;
        }
    }
    

    如果不需要保留数组键(不需要 $index ),但我认为这种差异可以忽略不计。

    使用 数组函数

    $filtered_array = [];
    foreach ($a as $index => $value) {
        if (!array_key_exists($value, $p)) {
            $filtered_array[$index] = $value;
        }
    }
    

    由于您不需要通过PHP错误处理的try/catch机制,因此速度会更快。

    如果你允许自己使用 unset() 要删除以下值: $p ,因此您不需要创建新数组,而是可以修改 在正确的位置根据您的代码示例和短数组语法,我假设您使用的是PHP 7。因为PHP 7不再使用内部数组指针 foreach 取消设置() 迭代时的项。如果您运行的是PHP 5,您仍然可以这样做,但您会面临以下风险: 跳过某些项目。

    foreach ($a as $index => $value) {
        if (array_key_exists($value, $p)) {
            unset($a[$index]);
        }
    }
    

    这样做将减少第二个(可能较大)阵列的内存开销。

    array_filter (虽然这不会修改现有阵列,但会构建新阵列,这将降低超大阵列的性能):

    $filtered_array = array_filter($a, function($value) use ($p) {
        return !array_key_exists($value, $p);
    });
    
        2
  •  -2
  •   vdegenne Kuba Å imonovský    7 年前

    所以我回答我自己的问题,人们太忙了,没法投反对票,还孩子气地说“这不可能”,“这是家庭作业吗?”。不,这不是家庭作业,我只是希望在这里得到一些帮助(你知道,就像 ).

    我试图实现的是,删除一个数组中的每个数字,该数组在另一个数组中有一个索引(两者都有不连续的值) 不使用任何功能 :

      // temporary $a
      $a_temp = [];
    
      foreach ($a as $avalue) {
          foreach ($p as $k => $v) {
              // if iterator $a is in the $p (we disregard)
              if ($avalue === $k) {
                continue 2;
              }
          }
          $a_temp[] = $avalue;
      }
    
      $a = $a_temp;
    

    (如果您看到上述功能,请给我发送电子邮件)


    这里有一些测试。

    /********************************
     * initialize fake data
     ********************************/
    $p = [];
    for ($i = 0; $i < 10; ++$i) {
        $p[rand(0, 500)] = null;
    }
    
    for ($j = 0; $j < 1000; ++$j) {
        $a[rand(0, 500)] = null;
    }
    $a = array_keys($a);
    
    
    
    /********************************
     * first test (without functions)
     ********************************/
    $start = microtime(true);
    
    for ($i = 0; $i < 9999; ++$i) {
    
      $a_temp = [];
    
      foreach ($a as $avalue) {
          foreach ($p as $k => $v) {
    
              if ($avalue === $k) {
                continue 2;
              }
          }
          $a_temp[] = $avalue;
      }
    }
    $firstTestExecTime = (microtime(true) - $start);
    // average time : 8s6757750511169
    
    
    
    /********************************
     * second test, with functions
     ********************************/
    $start = microtime(true);
    
    for ($i = 0; $i < 9999; ++$i) {
    
        $a_temp = [];
    
        foreach ($a as $avalue) {
    
          if (!array_key_exists($avalue, $p)) {
            $a_temp[] = $avalue;
          }
        }
    
    }
    $secondTestExecTime = (microtime(true) - $start);
    // average time : 5.1003220081329
    
    
    /********************************
     * printing results
     ********************************/
    printf('first test execution time : %s', $firstTestExecTime);
    printf('second test execution time : %s', $secondTestExecTime);
    

    array_search 比尝试生成本机代码具有更好的性能。