1

我有两个看起来像这样的多维数组:

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

我试图找到一种方法来确定哪些元素出现在一个数组 ( $b) 中,而不是另一个 ( $a) 中,以及是否有任何元素的值发生变化。如果$a是:

Array
(
    [0] => Array (
         'id' => 3,
         'other' => 'some string',
         'timestamp' => 2000-01-01 00:00:00
    )
)

并且$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
    )
)

然后函数应该返回:

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

因为元素 withid = 3已更改(timestamp字段),并且元素 withid = 4是新的并且不会出现在另一个数组中。

我一直在尝试用 来做到这一点array_udiff,但我仍然不知道它是如何工作的(它似乎首先对两个数组进行排序,但是它是如何进行比较的呢?)。是array_udiff正确的方法还是我应该编写自定义函数?

4

2 回答 2

3

您可以使用array_udiff和定义自己的比较回调。我假设两个数组具有完全相同的结构。

您可以定义自己的回调函数,如下所示:

int comparison(Array $a, Array $b){
    if ($a['id']==$b['id'] && $a['other']==$b['other'] && $a['timestamp']==$b['timestamp']){
        return 0
    }else{
        return -1
    }
}

如果第一个参数小于第二个,回调函数必须返回一个负整数;如果它更大,则为正数;如果相等,则为 0。然后,您可以返回任何不同于 0 的数字,以指示参数不同,如果它们相等,则返回 0。

最后,您应该array_udiff按以下方式调用:

array_udiff($a, $b, 'comparison')

您将获得一个列表,其中列出了$a其中不存在或不同的元素$b

请注意,如果要比较 2 个数组,其中一个数组的元素比另一个数组多,则应将数组与新元素作为第一个参数传递。

于 2013-08-20T18:01:34.077 回答
0

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;
}
于 2013-08-20T18:37:30.030 回答