PHP: search for all records from an array with a specific value

I have 2 arrays.

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

Now let's say for a specific entry in $ a having 'number' = 10. Is there a way in PHP so that I can extract all the addresses from $ b having 'number' = 10. I use foreach on but it takes too long , since I have more than 5,000 entries in $ a and more than 20,000 entries in $ b.

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

So, the result will be like this:

   $result = (
    ('number' => 10, 'name' => 'xyz', 'addresses' => array(<contains all addresses with number 10>) )
   )
+3
source share
5 answers

Here is a solution that only includes repeating each array, which should significantly reduce processing time:

$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
source

First, I think you need to rebuild the $ b array in the following format:

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

recovery:

$newB = array();

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

second find all addresses by number:

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

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
    );
}
+1

, .

It is so fast that the first limit will be limited by the memory limit of the script, so this is just an academic interest.

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>";

output:

short version done in 0.70000100135803s
long  version done in 1.5700018405914s
+1
source

I think that in this case you need to use some kind of algorithm, because speed is important to you.

There are many sorting algorithms. I would advise you to use Quicksort because it sorts very quickly; And in this case, sorting the array will save us a lot of time.

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

This is sorted very quickly, then the actual match is faster. After that, you can loop through the array and do a string comparison

0
source

All Articles