Question

I have two arrays, they both look like

array(
  array('key_id' => 1, 'value' => 4, 'whatever' => 'something'),
  array('key_id' => 2, 'value' => 3, 'whatever' => 'something'),
  array('key_id' => 3, 'value' => 2, 'whatever' => 'something'),
  array('key_id' => 4, 'value' => 1, 'whatever' => 'something'),
);

They will have some intersecting key_id's, there will be some that are present in the first array, but not the second, and some that are present in the second but not the first.

I want to get an array of all key_id's that are in the first array, but not the second. E.g.

$a = array(
  array('key_id' => 1, 'value' => 4, 'whatever' => 'something'),
  array('key_id' => 2, 'value' => 3, 'whatever' => 'something'),
  array('key_id' => 3, 'value' => 2, 'whatever' => 'something'),
);

$b = array(
  array('key_id' => 3, 'value' => 2, 'whatever' => 'something'),
  array('key_id' => 4, 'value' => 1, 'whatever' => 'something'),
);

The output I would want is array(1,2);

My current method is:

$keys = array('orig' => array(), 'new' => array());

array_map(function($array){
  $keys['orig'][] = $array['key_id'];
}, $a);

array_map(function ($array) {
  $keys['new'][] = $array['key_id'];
}, $b);

$difference = array_diff($keys['orig'], $keys['new']);

Which should work, but I am wondering if there is a better method?


Using eis's method below here is an working example of what I am doing to give context to the question:

<?php
$a = array(
  array('key_id' => 1, 'value' => 4, 'whatever' => 'something'),
  array('key_id' => 2, 'value' => 3, 'whatever' => 'something'),
  array('key_id' => 3, 'value' => 'o', 'whatever' => 'something'),
  array('key_id' => 5, 'value' => 'e', 'whatever' => 'something')
);

$b = array(
  array('key_id' => 3, 'value' => 'n', 'whatever' => 'something'),
  array('key_id' => 4, 'value' => 1, 'whatever' => 'something'),
  array('key_id' => 5, 'value' => 'e', 'whatever' => 'something')
));

function compareKeyId($a, $b) {
  if ($a['key_id'] === $b['key_id']) return 0;
  return ($a['key_id'] > $b['key_id']) ? 1 : -1;
}

function compareKeyIdAndValue($a, $b) {
    return ($a['key_id'] === $b['key_id'] && $a['value'] === $b['value']) ? 0 : -1;
  }

$changed = array();

$removed = array_udiff($a, $b, 'compareKeyId');
$added = array_udiff($b, $a, 'compareKeyId');

//get the elements that are present in both arrays (remainder)
$r = array();
$r['new'] = array_udiff($b, $removed, $added, 'compareKeyId');
$r['old'] = array_udiff($a, $removed, $added, 'compareKeyId');

$changed = array();
$changed['old'] = array_udiff($r['old'], $r['new'], 'compareKeyIdAndValue');
$changed['new'] = array_udiff($r['new'], $r['old'], 'compareKeyIdAndValue');

die('<pre>'.print_r(array('removed' => $removed, 'added' => $added, 'changed' => $changed), true).'</pre>');
?>
Was it helpful?

Solution

How about

// get the elements
function compare_col_key_id($a, $b) {
    if ($a['key_id'] === $b['key_id']) return 0;
    return ($a['key_id'] > $b['key_id']) ? 1 : -1;
}
$difference_elems = array_udiff($a, $b, 'compare_col_key_id');

// and if you just want the keys out
function get_col_key_id($a) {
    return $a['key_id'];
}
$difference_justkeys = array_map('get_col_key_id', $difference_elems);

What this does better is that it first filters the elements and then creates a key-only array only if needed and only for the already-filtered elements. Otherwise it's essentially the same thing, perhaps in a bit more clean way.

I would possibly wrap it in a class that would get column id in the constructor and have the functions above as methods, using the column id from a private variable.

OTHER TIPS

works correctly :

$a = array(
array('key_id' => 1, 'value' => 4, 'whatever' => 'something'),
array('key_id' => 2, 'value' => 3, 'whatever' => 'something'),
array('key_id' => 3, 'value' => 2, 'whatever' => 'something'),
);

$b = array(
array('key_id' => 3, 'value' => 2, 'whatever' => 'something'),
array('key_id' => 4, 'value' => 1, 'whatever' => 'something'),
);

$a1 = array_values($a);
$b1 = array_values($b);
for($i=0;$i<=count(a1);$i++){
   if( $a1[$i]['key_id'] != $b1[Si]['key_id'] ){
      $res[]=$a1[$i]['key_id'];
   }
}
print_r( $res );
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top