【问题标题】:PHP : Search all record from array with specific valuePHP:从具有特定值的数组中搜索所有记录
【发布时间】:2014-02-19 07:40:17
【问题描述】:

我有 2 个数组。

    $a = ( 
           array( 'number' => $value, 'name' => $name ),
           array( 'number' => $value, 'name' => $name ),
           array( 'number' => $value, 'name' => $name ), 
         );
    $b = ( 
           array( 'number' => $value, 'address' => $address ),
           array( 'number' => $value, 'address' => $address ),
           array( 'number' => $value, 'address' => $address ),
           ...
         );

现在,假设 $a 中的特定记录具有 'number' = 10。PHP 中有没有一种方法可以从 $b 中提取具有 'number' = 10 的所有地址。我正在使用 foreach时刻,但它需要太长时间,因为我在 $a 中有超过 5000 条记录,在 $b 中有超过 20000 条记录。

    $result = array();  

    foreach ($a as $tempA) {
      $result[]['number'] => $tempA['number'];
      $result[]['name'] => $tempA['name'];
      $address = array();

      foreach($b as $tempB) {
        if($tempB['number'] !== $tempA['number'])
          continue;
        $address[] = $tempB;
      }
      $result[]['addresses'] = $address;
    }

所以结果会是这样的:

   $result = (
    ('number' => 10, 'name' => 'xyz', 'addresses' => array(<contains all addresses with number 10>) )
   )

【问题讨论】:

  • 您能否展示您当前使用 foreach 的方法,以便更好地理解数据和预期结果?伪代码对我来说不是很清楚。
  • 所有这些数据都存储在哪里?
  • 编辑了问题。我希望它能解决我的问题。
  • @ponciste 数据存储在 mongoDB 数据库中
  • 使用查询不是更好吗?

标签: php


【解决方案1】:

这是一个只涉及对每个数组进行一次迭代的解决方案,这应该会显着减少所需的处理时间:

$a = array(
    array('number' => 1, 'name' => 'Bob'),
    array('number' => 2, 'name' => 'Sue'),
    array('number' => 3, 'name' => 'Jim'),
    array('number' => 4, 'name' => 'Cal'),
);

$b = array(
    array('number' => 1, 'address' => 'Address 1A'),
    array('number' => 1, 'address' => 'Address 1B'),
    array('number' => 1, 'address' => 'Address 1C'),
    array('number' => 2, 'address' => 'Address 2A'),
    array('number' => 2, 'address' => 'Address 2B'),
    array('number' => 4, 'address' => 'Address 4A'),
    array('number' => 4, 'address' => 'Address 4B'),
    array('number' => 4, 'address' => 'Address 4C'),
    array('number' => 4, 'address' => 'Address 4D'),
    array('number' => 4, 'address' => 'Address 4E'),
);

// Create array $c to index address records by key
$c = array();
foreach ($b as $item) {
    $key = $item['number'];
        if (!array_key_exists($key, $c)) {
            $c[$key] = array();
        }
        $c[$key][] = $item['address'];
}

// Now loop through $a creating the address on array $a by accessing $c by key
foreach ($a as $index => $item) {
    $key = $a[$index]['number'];
    $a[$index]['addresses'] = $c[$key];
}

// The result now lives in array $a
var_dump($a);

【讨论】:

    【解决方案2】:

    你可以使用array_*函数:

    function findAddressesByNumber($number, $names, $addresses){
        $found_names = array_values(
            array_filter($names, function ($v) use ($number) {
                return $v['number'] == $number;
            })
        );
        if (!count($found_names)) return false;
        $found_addrs = array_map(
            function ($v) { return $v['address']; },
            array_filter($addresses, function ($v) use ($number) {
                return $v['number'] == $number;
            })
        );
        return array(
            'number' => $number,
            'name' => $found_names[0]['name'],
            'addresses' => $found_addrs
        );
    }
    

    【讨论】:

      【解决方案3】:

      通过删除不必要的测试和中间变量,可以使所选解决方案的速度提高一倍。

      它太快了,遇到的第一个限制将是脚本内存限制,所以这只是学术兴趣。

      define ("MAX_NAMES", 50000);
      define ("ADDR_PER_NAME", 4);
      
      function create_arrays ()
      {
          $n = array();
          $a = array();
          for ($i = 0 ; $i != MAX_NAMES ; $i++)
          {
              $n[] = array ( 'number' => $i+1, 'name' => str_shuffle("abc") );
              for ($j = 0 ; $j != ADDR_PER_NAME ; $j++)
              {
                  $a[] = array ( 'number' => $i+1, 'address' => str_shuffle("abcdefghi"));
              }
          }
          shuffle($a);
          shuffle($n);
          return array ($n, $a);
      }
      
      //////////////////////////////////////////////////////////////////////////////////////
      
      list ($a, $b) = create_arrays();
      
      $start = microtime(true);
      foreach ($b as $item) $c[$item['number']][] = $item['address'];
      foreach ($a as $index => $item) $a[$index]['addresses'] = $c[$a[$index]['number']];
      echo "short version done in ".(microtime(true)-$start)."s<br>";
      
      $a=$b=$c=null; // to avoid hitting memory limit
      
      //////////////////////////////////////////////////////////////////////////////////////
      
      list ($a, $b) = create_arrays();
      
      $start = microtime(true);
      $c = array();
      foreach ($b as $item) {
          $key = $item['number'];
              if (!array_key_exists($key, $c)) {
                  $c[$key] = array();
              }
              $c[$key][] = $item['address'];
      }
      
      foreach ($a as $index => $item) {
          $key = $a[$index]['number'];
          $a[$index]['addresses'] = $c[$key];
      }
      echo "long version done in ".(microtime(true)-$start)."s<br>";
      

      输出:

      short version done in 0.70000100135803s
      long  version done in 1.5700018405914s
      

      【讨论】:

        【解决方案4】:

        首先,我认为您需要将数组 $b 重建为下一种格式:

        $newB = array('numberValue'=> array('address 1', 'address, 2', '...'));
        

        重建:

        $newB = array();
        
        foreach($b as $v)
        {
             $newB[$v['number'][] = $v['address'];
        }
        

        第二个按数字查找所有地址:

        forerach($a as $v){
            $newB[$v['number']]; 
            // get all address   
        }
        

        【讨论】:

          【解决方案5】:

          我认为在这种情况下你需要使用某种算法,因为速度对你来说至关重要。

          有很多排序算法。我建议您使用 Quicksort,因为它的排序速度非常快;在这种情况下,对数组进行排序将为我们节省大量时间。

          function quicksort($seq) {
              if(!count($seq)) return $seq;
              $pivot= $seq[0];
              $low = $high = array();
              $length = count($seq);
              for($i=1; $i < $length; $i++) {
                  if($seq[$i] <= $pivot) {
                      $low [] = $seq[$i];
                  } else {
                      $high[] = $seq[$i];
                  }
              }
              return array_merge(quicksort($low), array($pivot), quicksort($high));
          }
          var_dump(quicksort($a));
          

          这个排序很快,然后实际匹配更快。在此之后,您可以遍历数组并进行字符串比较

          【讨论】:

            猜你喜欢
            • 2022-07-12
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-12-12
            • 1970-01-01
            • 2018-03-17
            • 1970-01-01
            相关资源
            最近更新 更多