I have two multidimensional arrays that both look something like this:
我有两个多维数组,看起来像这样:
Array
(
[0] => Array (
'id' => 3,
'other' => 'some string',
'timestamp' => 2000-01-01 00:00:00
),
[1] => Array (
'id' => 6,
'other' => 'another string',
'timestamp' => 1835-01-01 00:00:00
)
)
I'm trying to find a way to figure out which elements show up in one array ($b
), but not the other ($a
) and if there are any elements with changed values. If $a
is:
我试图找到一种方法来确定哪个元素出现在一个数组($ b)中,而不是另一个($ a)以及是否有任何元素具有更改的值。如果$ a是:
Array
(
[0] => Array (
'id' => 3,
'other' => 'some string',
'timestamp' => 2000-01-01 00:00:00
)
)
and $b
is:
而$ b是:
Array
(
[0] => Array (
'id' => 3,
'other' => 'some string',
'timestamp' => 2000-01-01 12:12:12
),
[1] => Array (
'id' => 4,
'other' => 'some string',
'timestamp' => 1900-01-01 01:12:23
)
)
Then the function should return:
那么函数应该返回:
Array
(
[0] => Array (
'id' => 3,
'other' => 'some string',
'timestamp' => 2000-01-01 12:12:12
),
[1] => Array (
'id' => 4,
'other' => 'some string',
'timestamp' => 1900-01-01 01:12:23
)
)
because the element with id = 3
has been changed (the timestamp
field) and the element with id = 4
is new and doesn't appear in the other array.
因为id = 3的元素已被更改(时间戳字段),而id = 4的元素是新的,并且不会出现在另一个数组中。
I've been trying to do this with array_udiff
, but I still don't know how it works (it seems to sort both arrays first, but then how does it do comparison?). Is array_udiff
the proper method or should I write a custom function?
我一直在尝试用array_udiff做这个,但我仍然不知道它是如何工作的(它似乎首先对两个数组进行排序,但那么它如何进行比较?)。 array_udiff是正确的方法还是应该编写自定义函数?
2 个解决方案
#1
0
You can use array_udiff
and define your own comparison callback. I assume that both arrays has exactly the same structure.
您可以使用array_udiff并定义自己的比较回调。我假设两个阵列具有完全相同的结构。
You can define your own callback function as follow:
您可以定义自己的回调函数,如下所示:
int comparison(Array $a, Array $b){
if ($a['id']==$b['id'] && $a['other']==$b['other'] && $a['timestamp']==$b['timestamp']){
return 0
}else{
return -1
}
}
The callback function must return a negative integer if first argument is less than the second; a positive number if it's bigger; or 0 if it's equal. Then, you can return any number different to 0 to indicate that the arguments are different and 0 if they are the equal.
如果第一个参数小于第二个参数,则回调函数必须返回负整数;一个正数,如果它更大;如果相等则为0或0。然后,您可以返回任何不同的数字为0以指示参数不同,如果它们相等则返回0。
Finally, you should call array_udiff
as follow:
最后,你应该调用array_udiffas:
array_udiff($a, $b, 'comparison')
And you will get a list of the elements of $a
which are not, or are different in $b
.
并且您将获得$ a的元素列表,这些元素在$ b中不是或不同。
Note that if you want to compare 2 array when one of then has more elements than the other, you should pass as first argument the array with the new elements.
请注意,如果要比较2个数组,当其中一个元素的元素多于另一个时,您应该将具有新元素的数组作为第一个参数传递。
#2
0
The return for array_udiff function "data_compare_func" is some function that you define but it must return an integer less than, equal to, or greater than zero so its probably not the right function for your needs. A custom function like this should give you what you need:
array_udiff函数“data_compare_func”的返回值是您定义的某个函数,但它必须返回小于,等于或大于零的整数,因此它可能不是您需要的正确函数。像这样的自定义函数应该可以满足您的需求:
// this function loops through both arrays to find a match in the other array
// it will skip entry comparisons when it goes through $arr2 because you already did it the first time
function find_diff($arr1, $arr2) {
$ret = array();
// we need to do two loops to find missing entries from both arrays
$ret = do_loop($arr1, $arr2, $ret, true);
$ret = do_loop($arr2, $arr1, $ret, false);
return $ret;
}
// this function does the looping though $arr1 to compare it to entries in $arr2
// you can skip entry comparison if $compare_entries is false
function do_loop($arr1, $arr2, $ret, $compare_entries = true) {
//look through all of $arr1 for same element in $arr2 based on $id
for ($i=0;$i<count($arr1);$i++) {
$id = $arr1[$i]['id'];
$found = false;
for ($j=0;$j<count($arr2);$j++) {
// id match found
if ($id == $arr2[$j]['id']) {
$found = true;
// only compare entries if you need to
if ($compare_entries) {
//check if other field is different
if (strcmp($arr1[$i]['other'],$arr2[$j]['other']) != 0) {
$ret = add_to_ret($arr1[$i], $ret);
break;
}
//check if timestamp field is different
if (strcmp($arr1[$i]['timestamp'],$arr2[$j]['timestamp']) != 0) {
$ret = add_to_ret($arr1[$i], $ret);
break;
}
} else {
break;
}
}
}
// entry from $arr1[$i] was not found in $arr2
if (!$found) {
$ret = add_to_ret($arr1[$i], $ret);
}
}
return $ret;
}
//this function only adds the new entry to $ret if it's ID isn't already in $ret
function add_to_ret($entry, $ret) {
$id = $entry['id'];
for ($i=0;$i<count($ret);$i++) {
if ($id == $ret[$i]['id']) {
//skip adding, its already in there
return $ret;
}
}
//add it in
$ret[] = $entry;
return $ret;
}
#1
0
You can use array_udiff
and define your own comparison callback. I assume that both arrays has exactly the same structure.
您可以使用array_udiff并定义自己的比较回调。我假设两个阵列具有完全相同的结构。
You can define your own callback function as follow:
您可以定义自己的回调函数,如下所示:
int comparison(Array $a, Array $b){
if ($a['id']==$b['id'] && $a['other']==$b['other'] && $a['timestamp']==$b['timestamp']){
return 0
}else{
return -1
}
}
The callback function must return a negative integer if first argument is less than the second; a positive number if it's bigger; or 0 if it's equal. Then, you can return any number different to 0 to indicate that the arguments are different and 0 if they are the equal.
如果第一个参数小于第二个参数,则回调函数必须返回负整数;一个正数,如果它更大;如果相等则为0或0。然后,您可以返回任何不同的数字为0以指示参数不同,如果它们相等则返回0。
Finally, you should call array_udiff
as follow:
最后,你应该调用array_udiffas:
array_udiff($a, $b, 'comparison')
And you will get a list of the elements of $a
which are not, or are different in $b
.
并且您将获得$ a的元素列表,这些元素在$ b中不是或不同。
Note that if you want to compare 2 array when one of then has more elements than the other, you should pass as first argument the array with the new elements.
请注意,如果要比较2个数组,当其中一个元素的元素多于另一个时,您应该将具有新元素的数组作为第一个参数传递。
#2
0
The return for array_udiff function "data_compare_func" is some function that you define but it must return an integer less than, equal to, or greater than zero so its probably not the right function for your needs. A custom function like this should give you what you need:
array_udiff函数“data_compare_func”的返回值是您定义的某个函数,但它必须返回小于,等于或大于零的整数,因此它可能不是您需要的正确函数。像这样的自定义函数应该可以满足您的需求:
// this function loops through both arrays to find a match in the other array
// it will skip entry comparisons when it goes through $arr2 because you already did it the first time
function find_diff($arr1, $arr2) {
$ret = array();
// we need to do two loops to find missing entries from both arrays
$ret = do_loop($arr1, $arr2, $ret, true);
$ret = do_loop($arr2, $arr1, $ret, false);
return $ret;
}
// this function does the looping though $arr1 to compare it to entries in $arr2
// you can skip entry comparison if $compare_entries is false
function do_loop($arr1, $arr2, $ret, $compare_entries = true) {
//look through all of $arr1 for same element in $arr2 based on $id
for ($i=0;$i<count($arr1);$i++) {
$id = $arr1[$i]['id'];
$found = false;
for ($j=0;$j<count($arr2);$j++) {
// id match found
if ($id == $arr2[$j]['id']) {
$found = true;
// only compare entries if you need to
if ($compare_entries) {
//check if other field is different
if (strcmp($arr1[$i]['other'],$arr2[$j]['other']) != 0) {
$ret = add_to_ret($arr1[$i], $ret);
break;
}
//check if timestamp field is different
if (strcmp($arr1[$i]['timestamp'],$arr2[$j]['timestamp']) != 0) {
$ret = add_to_ret($arr1[$i], $ret);
break;
}
} else {
break;
}
}
}
// entry from $arr1[$i] was not found in $arr2
if (!$found) {
$ret = add_to_ret($arr1[$i], $ret);
}
}
return $ret;
}
//this function only adds the new entry to $ret if it's ID isn't already in $ret
function add_to_ret($entry, $ret) {
$id = $entry['id'];
for ($i=0;$i<count($ret);$i++) {
if ($id == $ret[$i]['id']) {
//skip adding, its already in there
return $ret;
}
}
//add it in
$ret[] = $entry;
return $ret;
}