如何将特定数据类型的差异编码到数组中


How to get the difference of specific data types encoded into arrays

如何获得包含数据类型的数组的差异?

第一个数组:

Array
(
  [0] => Array
  (
    [ID] => 21323154
    [NAME] => Name_2
    [PREVIEW_TEXT] => Text_2
  )
)

第二个数组:

Array
(
  [0] => Array
  (
    [ID] => 543547564
    [NAME] => Name_1
    [PREVIEW_TEXT] => Text_1
  )
  [1] => Array
  (
    [ID] => 222213322
    [NAME] => Name_2
    [PREVIEW_TEXT] => Text_2
  )
  [2] => Array
  (
    [ID] => 333876833
    [NAME] => Name_3
    [PREVIEW_TEXT] => Text_3
  )
)

结果应该是一个数组

Array
(
  [0] => Array
  (
    [ID] => 543547564
    [NAME] => Name_1
    [PREVIEW_TEXT] => Text_1
  )
  [1] => Array
  (
    [ID] => 333876833
    [NAME] => Name_3
    [PREVIEW_TEXT] => Text_3
  )
)

我尝试了不同的选项,但它们都返回了发现差异的结果,即第一个数组。

我有一个不同的ID

试试:

$output = array_udiff($arraySecond, $arrayFirst, function($a, $b){
    return strcmp($a['NAME'], $b['NAME']);;
});
输出:

array(2) {
  [0] =>
  array(3) {
    'ID' =>
    int(543547564)
    'NAME' =>
    string(6) "Name_1"
    'PREVIEW_TEXT' =>
    string(6) "Text_1"
  }
  [2] =>
  array(3) {
    'ID' =>
    int(333876833)
    'NAME' =>
    string(6) "Name_3"
    'PREVIEW_TEXT' =>
    string(6) "Text_3"
  }
}

如果两个数组都很大,array_diff将非常低效,因为它将第一个数组的每个元素与第二个数组的每个元素进行比较。一个更快的解决方案是将这个过程分成两个步骤:首先,生成一组要删除的键:

 $remove = array();
 foreach($firstArray as $item)
      $remove[$item['name']] = 1;

,然后遍历第二个数组,并将"good"项添加到结果中:

 $result = array(); 
 foreach($secondArray as $item)
      if(!isset($remove[$item['name']]))
           $result []= $item;

这将为您提供线性性能,而array_diff是二次的。

根据您想要的字段(列)对两个数组进行Diff,然后只返回那些条目(多亏了键):

$col  = 'NAME';
$diff = array_intersect_key($b, array_diff(array_column($b, $col), array_column($a, $col)));
print_r($diff);

如果你喜欢这个不那么二次但线性的,你也可以通过迭代来解决它(灵感来自georg的答案,但再次使用array_column()):

$filtered = function ($col, $a, $b) {
    return iterator_to_array(call_user_func(function () use ($col, $a, $b) {
        $coled = array_flip(array_column($a, $col));
        foreach ($b as $bk => $bv) if (!isset($coled[$bv[$col]])) yield $bk => $bv;
    }));
};
print_r($filtered('NAME', $a, $b));

使用概述的$a$b,您将获得以下两个示例的结果:

Array
(
    [0] => Array
        (
            [ID] => 543547564
            [NAME] => Name_1
            [PREVIEW_TEXT] => Text_1
        )
    [2] => Array
        (
            [ID] => 333876833
            [NAME] => Name_3
            [PREVIEW_TEXT] => Text_3
        )
)

// 1.) - diff against column, intersect keys
$filtered = function($col, $a, $b) {
    return array_intersect_key($b, array_diff(array_column($b, $col), array_column($a, $col)));
};
// 2.) - iterate and take only unset by column
$filtered = function ($col, $a, $b) {
    return iterator_to_array(call_user_func(function () use ($col, $a, $b) {
        $coled = array_flip(array_column($a, $col));
        foreach ($b as $bk => $bv) if (!isset($coled[$bv[$col]])) yield $bk => $bv;
    }));
};
// 3.) - array_udiff against column
$filtered = function($col, $a, $b) {
    return array_udiff($b, $a, function ($a, $b) use ($col) {
        return strcmp($a[$col], $b[$col]);
    });
};

用法:

print_r($filtered('NAME', $a, $b));

其中$a是包含要从$b数组中移除的元素的数组。因此,$a是问题的第一个数组,$b是问题的第二个数组。