PHP:从具有特定值的数组中搜索所有记录

时间:2014-02-19 07:40:18

标签: php

我有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>) )
   )

5 个答案:

答案 0 :(得分:2)

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

$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);

答案 1 :(得分:1)

首先我认为你需要重建你的数组$ 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 }

答案 2 :(得分:1)

您可以使用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 :(得分:1)

通过删除不必要的测试和中间变量,可以使选定的解决方案快两倍。

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

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 :(得分:0)

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

有很多排序算法。我建议你使用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));

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