我正在尋找一些工具來給我一個兩個數組的遞歸差異。我設想的是一個帶有兩種顏色編碼的樹狀結構的網頁。在每棵樹上,綠色都是數組中與兩個數組相匹配的部分,紅色表示每個數組中不匹配的部分。類似於dBug的輸出recursive array_diff()?
我有一些代碼給了我一個嵌套數組來填充報表。我正在開發一種應該更快的新方法,但我需要測試值和結構,以確保它的輸出與舊方法相同。
我有什麼可以使用的東西嗎?或者我需要寫這個?還是有另一種方法來實現我的目標?
我正在尋找一些工具來給我一個兩個數組的遞歸差異。我設想的是一個帶有兩種顏色編碼的樹狀結構的網頁。在每棵樹上,綠色都是數組中與兩個數組相匹配的部分,紅色表示每個數組中不匹配的部分。類似於dBug的輸出recursive array_diff()?
我有一些代碼給了我一個嵌套數組來填充報表。我正在開發一種應該更快的新方法,但我需要測試值和結構,以確保它的輸出與舊方法相同。
我有什麼可以使用的東西嗎?或者我需要寫這個?還是有另一種方法來實現我的目標?
在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;
}
該實現一次只處理兩個數組,但我不認爲這確實存在問題。如果您一次需要3個或更多數組的差異,則可以按順序運行差異。此外,此方法使用密鑰檢查並進行寬鬆驗證。
它的工作原理。感謝這一點。 –
@Zend_Sklave,因爲mhitza的答案爲你工作,你應該把它標記爲實際回答你的請求... –
@JonL。我認爲他必須成爲這個問題的作者:) – user151841
接受的答案接近正確,但它並沒有真正模擬array_diff
正確。
有兩個問題在很大程度上圍繞密鑰匹配:
array_diff
具有特定的行爲,其中它不產生結果爲如果其值,它是完全從所述第二陣列缺少的陣列鍵仍然在第二個數組中。如果您有兩個數組$first = ['foo' => 2, 'moo' => 2]
和$second = ['foo' => 2]
,使用接受的答案函數,輸出將是['moo' => 2]
。如果通過array_diff
運行相同的數組,它將產生一個空數組。這是因爲上述函數的最後else
語句將其添加到diff,如果數組鍵不見了,但這不是array_diff
的預期行爲。這兩個陣列也是如此:$first = ['foo' => 1]
和$second = [1]
。 array_diff
將產生一個空數組。
如果兩個數組具有相同的值但鍵不同,它將返回比預期更多的值。如果您有兩個陣列$foo = [1, 2]
和$moo = [2, 1]
,則接受的答案中的函數將輸出來自$foo
的所有值。這是因爲它在每次迭代時都進行嚴格的密鑰匹配,在兩次數組中找到相同的鍵(數字或其他)而不是檢查第二個數組中的所有其他值。
下面的函數是相似的,但更緊密的作用是你期待怎樣array_diff
工作(也有少傻變量名):
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;
}
試試這個代碼:
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);
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;
}
實施例:
$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'
)
);
輸出:
array_diff_assoc_recursive($a,$b);
Array
(
[product_a] => Array
(
[color] => Red
[serial] => Array
(
[2] => 3
)
)
)
難道_just_臨時測試這些輸出,或更長的使用?它是一個測試,一個簡單的'wdiff'超過'var_export'輸出應該做的訣竅... – Wrikken
在嵌套結構中,如果一個元素是一個數組6,而另一個是數組3,那麼這次旅行'wdiff'?因爲在輸出中,從0到30行將是相同的,並且從結尾回到36行它將是相同的。只有那些中線會有所不同 - 3對6.如果wdiff看這個,它會被絆倒嗎? – user151841
輸出不會在鍵/值對中漂亮地分割,然而它會盡力匹配之前和之後的線以進一步匹配,而恕我直言,如果我只是區分檢查,它會這樣做。只需使用一個簡單的[testscript here](http://pastebin.com/wrwXw5zT),看看你的目的是否足夠好。另一種選擇是遞歸函數,但並不那麼困難,但是更多的工作。 – Wrikken