Hướng dẫn dùng diff recursive trong PHP

answer

69

Hướng dẫn dùng diff recursive trong PHP

Có một hàm như vậy được thực hiện trong các bình luận của array_diff .

function arrayRecursiveDiff($aArray1, $aArray2) {
  $aReturn = array();

  foreach ($aArray1 as $mKey => $mValue) {
    if (array_key_exists($mKey, $aArray2)) {
      if (is_array($mValue)) {
        $aRecursiveDiff = arrayRecursiveDiff($mValue, $aArray2[$mKey]);
        if (count($aRecursiveDiff)) { $aReturn[$mKey] = $aRecursiveDiff; }
      } else {
        if ($mValue != $aArray2[$mKey]) {
          $aReturn[$mKey] = $mValue;
        }
      }
    } else {
      $aReturn[$mKey] = $mValue;
    }
  }
  return $aReturn;
} 

Việc triển khai chỉ xử lý hai mảng cùng một lúc, nhưng tôi không nghĩ rằng điều đó thực sự có vấn đề. Bạn có thể chạy khác biệt tuần tự nếu bạn cần khác biệt của 3 mảng trở lên cùng một lúc. Ngoài ra, phương pháp này sử dụng kiểm tra khóa và xác minh lỏng lẻo.

69 hữu ích 5 bình luận chia sẻ

answer

16

Hướng dẫn dùng diff recursive trong PHP

Câu trả lời được chấp nhận gần đúng, nhưng nó không thực sự mô phỏng array_diffchính xác.

Có hai vấn đề chủ yếu xoay quanh việc khớp khóa:

  1. array_diffcó một hành vi cụ thể trong đó nó không tạo ra kết quả cho một khóa mảng bị thiếu hoàn toàn trong mảng thứ hai nếu giá trị của nó vẫn nằm trong mảng thứ hai. Nếu bạn có hai mảng $first = ['foo' => 2, 'moo' => 2]$second = ['foo' => 2]sử dụng hàm của câu trả lời được chấp nhận, đầu ra sẽ là ['moo' => 2]. Nếu bạn chạy cùng một mảng array_diff, nó sẽ tạo ra một mảng trống. Điều này là do elsecâu lệnh cuối cùng của hàm trên thêm nó vào khác biệt nếu thiếu khóa mảng, nhưng đó không phải là hành vi mong đợi từ đó array_diff. Điều này cũng đúng với hai mảng này: $first = ['foo' => 1]$second = [1]. array_diffsẽ tạo ra một mảng trống.

  2. Nếu hai mảng có cùng giá trị nhưng khác khóa, nó sẽ trả về nhiều giá trị hơn mong đợi. Nếu bạn có hai mảng $foo = [1, 2]$moo = [2, 1], hàm từ câu trả lời được chấp nhận sẽ xuất ra tất cả các giá trị từ $foo. Điều này là do nó thực hiện khớp khóa chặt chẽ trên mỗi lần lặp, nơi nó tìm thấy cùng một khóa (số hoặc cách khác) trong cả hai mảng thay vì kiểm tra tất cả các giá trị khác trong mảng thứ hai.

Hàm sau đây tương tự, nhưng hoạt động chặt chẽ hơn với cách bạn mong đợi array_diffhoạt động (cũng với các tên biến ít ngớ ngẩn hơn):

function array_diff_recursive($arr1, $arr2)
{
    $outputDiff = [];

    foreach ($arr1 as $key => $value)
    {
        //if the key exists in the second array, recursively call this function 
        //if it is an array, otherwise check if the value is in arr2
        if (array_key_exists($key, $arr2))
        {
            if (is_array($value))
            {
                $recursiveDiff = array_diff_recursive($value, $arr2[$key]);

                if (count($recursiveDiff))
                {
                    $outputDiff[$key] = $recursiveDiff;
                }
            }
            else if (!in_array($value, $arr2))
            {
                $outputDiff[$key] = $value;
            }
        }
        //if the key is not in the second array, check if the value is in 
        //the second array (this is a quirk of how array_diff works)
        else if (!in_array($value, $arr2))
        {
            $outputDiff[$key] = $value;
        }
    }

    return $outputDiff;
}

16 hữu ích 5 bình luận chia sẻ

answer

5

Hướng dẫn dùng diff recursive trong PHP

function array_diff_assoc_recursive($array1, $array2)
{
    foreach($array1 as $key => $value){

        if(is_array($value)){
            if(!isset($array2[$key]))
            {
                $difference[$key] = $value;
            }
            elseif(!is_array($array2[$key]))
            {
                $difference[$key] = $value;
            }
            else
            {
                $new_diff = array_diff_assoc_recursive($value, $array2[$key]);
                if($new_diff != FALSE)
                {
                    $difference[$key] = $new_diff;
                }
            }
        }
        elseif((!isset($array2[$key]) || $array2[$key] != $value) && !($array2[$key]===null && $value===null))
        {
            $difference[$key] = $value;
        }
    }
    return !isset($difference) ? 0 : $difference;
}

Thí dụ:

$a = array(
    "product_a" => array(
        'description'=>'Product A',
        'color'=>'Red',
        'quantity'=>'5',
        'serial'=>array(1,2,3)
    ),
    "product_b" => array(
        'description'=>'Product B'
    )
);

$b = array(
    "product_a" => array(
        'description'=>'Product A',
        'color'=>'Blue',
        'quantity'=>'5',
        'serial'=>array(1,2,5)
    ),
    "product_b" => array(
        'description'=>'Product B'
    )
);

Đầu ra:

array_diff_assoc_recursive($a,$b);

Array
(
    [product_a] => Array
        (
            [color] => Red
            [serial] => Array
                (
                    [2] => 3
                )    
        )    
)

5 hữu ích 0 bình luận chia sẻ

answer

2

Hướng dẫn dùng diff recursive trong PHP

Hãy thử mã này:

function arrayDiffRecursive($firstArray, $secondArray, $reverseKey = false)
{
    $oldKey = 'old';
    $newKey = 'new';
    if ($reverseKey) {
        $oldKey = 'new';
        $newKey = 'old';
    }
    $difference = [];
    foreach ($firstArray as $firstKey => $firstValue) {
        if (is_array($firstValue)) {
            if (!array_key_exists($firstKey, $secondArray) || !is_array($secondArray[$firstKey])) {
                $difference[$oldKey][$firstKey] = $firstValue;
                $difference[$newKey][$firstKey] = '';
            } else {
                $newDiff = arrayDiffRecursive($firstValue, $secondArray[$firstKey], $reverseKey);
                if (!empty($newDiff)) {
                    $difference[$oldKey][$firstKey] = $newDiff[$oldKey];
                    $difference[$newKey][$firstKey] = $newDiff[$newKey];
                }
            }
        } else {
            if (!array_key_exists($firstKey, $secondArray) || $secondArray[$firstKey] != $firstValue) {
                $difference[$oldKey][$firstKey] = $firstValue;
                $difference[$newKey][$firstKey] = $secondArray[$firstKey];
            }
        }
    }
    return $difference;
}

$differences = array_replace_recursive(
    arrayDiffRecursive($firstArray, $secondArray),
    arrayDiffRecursive($secondArray, $firstArray, true)
);
var_dump($differences);

2 hữu ích 0 bình luận chia sẻ

answer

0

Hướng dẫn dùng diff recursive trong PHP

Câu trả lời của Mohamad đang hoạt động tốt, ngoại trừ việc nó cần thay đổi trên dòng:

$difference[$newKey][$firstKey] = $secondArray[$firstKey];

với:

$difference[$newKey][$firstKey] = array_key_exists($firstKey, $secondArray) ? $secondArray[$firstKey] : null;

hoặc, nếu bạn đang sử dụng Laravel, với:

$difference[$newKey][$firstKey] = array_get($secondArray, $firstKey);

Nếu không, bạn sẽ gặp những lỗi như

Lỗi PHP: Chỉ mục không xác định: some_key

khi một some_key tồn tại trong $ secondArray nhưng không tồn tại trong $ firstArray

0 hữu ích 0 bình luận chia sẻ