Write a function that accepts two deeply nested objects or arrays obj1 and obj2 and returns a new object representing their differences.
寫一個函式可以接受兩個深度巢狀的物件或陣列(obj1, obj2),和回傳一個新物件來表示他們的差異。
The function should compare the properties of the two objects and identify any changes. The returned object should only contains keys where the value is different from obj1 to obj2. For each changed key, the value should be represented as an array [obj1 value, obj2 value]. Keys that exist in one object but not in the other should not be included in the returned object. When comparing two arrays, the indices of the arrays are considered to be their keys. The end result should be a deeply nested object where each leaf value is a difference array.
這個函式應該比較兩個物件的屬性和辨識出任何的更改,回傳的物件應該僅包含在 obj1 和 obj2 之間的 key。 每一個改變的 key,他的值應該被標示為陣列[obj1 value, obj2 value]。 key 不存在於其中一個物件中,則不應包含在回傳的物件中,當比較兩個陣列時,陣列的索引被視為它們的 key。 最終結果應是一個巢狀的物件,其中每個子值都是一個顯示差異的陣列。
You may assume that both objects are the output of JSON.parse.
您可以假設這兩個物件都是 JSON.parse 的結果。
Example 1:
Input: obj1 = {} obj2 = { "a": 1, "b": 2 } Output: {}
Example 2:
Input: obj1 = { "a": 1, "v": 3, "x": [], "z": { "a": null } } obj2 = { "a": 2, "v": 4, "x": [], "z": { "a": 2 } } Output: { "a": [1, 2], "v": [3, 4], "z": { "a": [null, 2] } }
Example 3:
Input: obj1 = { "a": 5, "v": 6, "z": [1, 2, 4, [2, 5, 7]] } obj2 = { "a": 5, "v": 7, "z": [1, 2, 3, [1]] } Output: { "v": [6, 7], "z": { "2": [4, 3], "3": { "0": [2, 1] } } }
Example 4:
Input: obj1 = { "a": {"b": 1}, } obj2 = { "a": [5], } Output: { "a": [{"b": 1}, [5]] }
Example 5:
Input: obj1 = { "a": [1, 2, {}], "b": false } obj2 = { "b": false, "a": [1, 2, {}] } Output: {}
solution:
宣告一個函式來處理兩個物件的差異:
1. 先建立判斷物件的 isObject() function(排除null)。
2. 宣告 diff 為空物件,同時運用 for in 迴圈來將 obj2 當作比較的基準。
3. 運用 if 判斷式來確認 obj2 物件中是否含有符合的 key。
4. 建立 res 為遞迴函式,進行以下判斷與回傳結果:
4-1. 判斷 obj1、obj2 兩者皆不是物件,使用三元運算子判斷兩者相同則回傳{},反之回傳[obj1, obj2]。
4-2. 如果 obj1、obj2 其中一個不是物件,則將之放入陣列後回傳[obj1, obj2]。
4-3. 如果 obj1、obj2 其中一個不是陣列,則將之放入陣列後回傳[obj1, obj2]。
5. 如果遞迴函式回傳有內容的物件,則將 res 放入對應 diff 的 key 位置。
6. 回傳 diff 物件。
Code 1: BigO(n)
function objDiff(obj1, obj2) { //Example Table //+--------------------------+---------------------+------------------------------------+ //| obj1 | obj2 | res | //+--------------------------+---------------------+------------------------------------+ //| {} | "a": 1 | {} | Example.1 //| "a": 1 | "a": 2 | {"a": [1, 2]} | Example.2 //| "z":{"a": null} | "z":{"a": 2} | {"z":{"a": [null, 2]}} | Example.2 //| "z":[1, 2, 4, [2, 5, 7]] | "z": [1, 2, 3, [1]] |{"z":{ "2": [4,3],"3":{"0": [2,1]}}}| Example.3 //| "a": {"b": 1} | "a": [5] | {"a": [{"b": 1}, [5]]} | Example.4 //| "a": [1, 2, {}] | "a": [1, 2, {}] | {} | Example.5 //| "a": [1, 2, {}] | false | { a: [ [ 1, 2, {} ], false ] } | Example.6 //+--------------------------+---------------------+------------------------------------+ //both primitive if (!isObject(obj1) && !isObject(obj2)) return obj1 === obj2 ? {} : [obj1, obj2] //one primitive if (!isObject(obj1) || !isObject(obj2)) return [obj1, obj2] //one array, one obj if (Array.isArray(obj1) !== Array.isArray(obj2)) return [obj1, obj2] const diff = {} for (const key in obj1) { if (obj2.hasOwnProperty(key)) { const res = objDiff(obj1[key], obj2[key]) if (Object.keys(res).length > 0) { diff[key] = res } } } return diff; function isObject(obj) { return obj !== null && typeof obj === "object" } };
FlowChart:
Example 1
console.log(objDiff({},{ "a": 1, "b": 2 })) //{}
Example 2
console.log(objDiff({ "a": 1, "v": 3, "x": [], "z": { "a": null } },{ "a": 2, "v": 4, "x": [], "z": { "a": 2 } })) //{ a: [ 1, 2 ], v: [ 3, 4 ], z: { a: [ null, 2 ] } }
Example 3
console.log(objDiff({ "a": 5, "v": 6, "z": [1, 2, 4, [2, 5, 7]] },{ "a": 5, "v": 7, "z": [1, 2, 3, [1]] })) //{ v: [ 6, 7 ], z: { '2': [ 4, 3 ], '3': { '0': [ 2, 1 ] } } }
Example 4
console.log(objDiff({ "a": {"b": 1}, },{ "a": [5], })) //{ a: [ { b: 1 }, [ 5 ] ] }
Example 5
console.log(objDiff({ "a": [1, 2, {}], "b": false },{ "b": false, "a": [1, 2, {}] })) //{}