0

I want to filter a array by a number and update its status in the first array.

I have two array $arr1,$arr2

$arr1 = array(
    0=>array('number'=>100,name=>'john'),
    1=>array('number'=>200,name=>'johnny')
);
$arr2= array(
    0=>array('number'=>300,name=>'r'),
    1=>array('number'=>100,name=>'b'),
    2=>array('number'=>200,name=>'c')
);

Final output should be an array like this

$arr1 = array(
    0=>array('number'=>100,name=>'b'),
    1=>array('number'=>200,name=>'c')
);

Any ideas to start off please ?

5
  • How are you retrieving this data? Because it would be a heck of a lot simpler if you have meaningful keys instead of having to inspect the number part... Commented May 15, 2013 at 18:36
  • Based on the number from second array update the name part of first array. Commented May 15, 2013 at 18:38
  • That's not what I'm asking. I'm asking whether we can simplify this problem at the source rather then do some redundant loops later. Commented May 15, 2013 at 18:39
  • array_intersect read about it Commented May 15, 2013 at 18:49
  • @RobertPodwika array_intersect($arr1, $arr2) wouldn't work here, it does a naive string comparison. It would either include all elements from both arrays, or none. array-uinstersect with a custom comparison would get closer, but it wouldn't transform the first array. OP doesn't specify what he wants to do with elements in the $arr1 but not in $arr2, but the implication is that they would remain in $arr1, where as intersection would remove them. Commented May 15, 2013 at 19:05

4 Answers 4

2

For specialized array modifications like this, the method of choice is array walk. It allows you to apply a custom function to each element in a given array.

Now, because of your data format, you will have to do a loop. Wrikken is asking if you can retrieve or transform the data to provide faster access. The algorithm below is O(n^2): it will require as many cycles as there are elements in the first array times the number of elements in the second array, or exactly count($arr1) * count($arr2).

function updateNameFromArray($element, $key, $arr2) {
    foreach($arr2 as $value) {
        if($value['number'] == $element['number']) {
            $element['name'] == $value['name'];
            break;
        }
    }
}

array_walk($arr1, "updateNameFromArray", $arr2);

Now, what Wrikken is suggesting is that if your arrays can be changed to be keyed on the 'number' property instead, then the search/replace operation is much easier. So if this were your data instead:

$arr1 = array(
    100=>array('number'=>100,name=>'john'),
    200=>array('number'=>200,name=>'johnny')
);
// notice the keys are 100 and 200 instead of 0,1

$arr2= array(
    300=>array('number'=>300,name=>'r'),
    100=>array('number'=>100,name=>'b'),
    200=>array('number'=>200,name=>'c')
);
// notice the keys are 300, 100 and 200 instead of 0,1, 2

Then you could do this in O(n) time, with only looping over the first array.

foreach($arr1 as $key => $value) {
    if(isset($arr2[$key])) {
        $value['number'] = $arr2[$key]['number'];
    }
}
Sign up to request clarification or add additional context in comments.

Comments

2

Try this. It's not that clean but i think it would work.

<?php

 $arr1 = array(0=>array('number'=>100,'name'=>'john'),1=>array('number'=>200,'name'=>'johnny'));
 $arr2= array(0=>array('number'=>300,'name'=>'r'),1=>array('number'=>100,'name'=>'b'),2=>array('number'=>200,'name'=>'c'));
 foreach( $arr1 as $key=>$data1 )
  {
foreach( $arr2 as $key2=>$data2 )
{
    if( $data1['number'] == $data2['number'] )
    {
        $arr1[$key]['name'] = $arr2[$key2]['name'];
    }
 }

  }
 print_r( $arr1 );
?>

the output would be :

Array
(
[0] => Array
    (
        [number] => 100
        [name] => b
    )

[1] => Array
    (
        [number] => 200
        [name] => c
    )

)

Comments

1

There isn't really a simple way for this to be accomplished with generic PHP functions, so, You might need to create mapping arrays.

The way I would approach this, is creating a loop that goes through the first array, and maps the number value as a key to the index of it's place in $arr1 giving you:

$tmp1 = array();
foreach ($arr1 as $key => $number_name) {
  $tmp1[$number_name['number']] = $key;
}

This should give you an array that looks like

$tmp1 [
  100 => 0,
  200 => 1
];

Then I would loop through the second array, get the number value, if that existed as a key in $tmp1, get the associated value (being the key for $arr1), and use that to update the name in $arr1.

// Loop through $arr2
foreach ($arr2 as $number_name) {
  // Get the number value
  $number = $number_name['number'];

  // Find the $arr1 index 
  if (isset($tmp1[$number])) {
    $arr1_key = $tmp1[$number];
    // Set the $arr1 name value
    $arr1[$arr1_key]['name'] = $number_name['name'];
  }
}

Comments

0
<?php 

//Set the arrays

$arr1 = array(
    array('number'=>100,'name'=>'john'),
    array('number'=>200,'name'=>'johnny')
);

$arr2= array(
    array('number'=>300,'name'=>'r'),
    array('number'=>100,'name'=>'b'),
    array('number'=>200,'name'=>'c')
);

// use a nested for loop to iterate and compare both arrays

for ($i=0;$i<count($arr1);$i++):

    for ($j=0;$j<count($arr2);$j++):

        if ($arr2[$j]['number']==$arr1[$i]['number'])
            $arr1[$i]['name']=$arr2[$j]['name'];

    endfor;

endfor;

print_r($arr1);

OUTPUT:

 Array (
 [0] => Array ( [number] => 100 [name] => b )
 [1] => Array ( [number] => 200 [name] => c )
 )

That being said, you should probably reconsider the very way your data is structured. Do you really need a multi-dimensional array or can you use a simple associative array, like so:

 // set the arrays

 $arr1 = array(
        'john'=>100,
        'johnny'=>200          
    );

 $arr2 = array(
       'r'=>300,
       'b'=>100,
       'c'=>200
     );

// find values in arr2 common to both arrays

$arr3 = array_intersect($arr2, $arr1);

// change the key of arr1 to match the corresponding key in arr2

  foreach ($arr3 as $key=>$value) {

      $old_key = array_search($value, $arr1);
      $arr1[$key]=$arr1[$old_key];
      unset($arr1[$old_key]);

  }


print_r($arr1);

OUTPUT:

Array ( 
   [b] => 100 
   [c] => 200 
)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.