Skip to content

Commit 2d64d33

Browse files
committed
Merge branch 'rachleona-master'
USER:rachleona added deepcompare algorithm on Repository.
2 parents c877dea + 6d78de2 commit 2d64d33

File tree

2 files changed

+115
-4
lines changed

2 files changed

+115
-4
lines changed

README.md

Lines changed: 96 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -562,15 +562,107 @@ Note that we chain both .replace() methods in succession such that both cases ar
562562
<hr>
563563
<hr>
564564
565-
<b>7. Name </b>
565+
<b>7. Deep Comparison </b>
566566
567-
__The challenge:__ <p> </p>
567+
Comparing objects can be troublesome, not to mention multi-dimensional objects/arrays. Here is something simple to help.
568568
569+
__The challenge:__ <p> - JS Objects, contrary to the way we perceive it, are simply pointers to the data stored, rather than the actual data itself. Thus, to compare objects/arrays a and b we cannot just use normal comparison operators.</p>
570+
```js
571+
a === b //false
572+
```
573+
<p> - Use of multidimensional objects/arrays is possible, making it difficult to compare simply by iteration since we don't know the depth of a value. </p>
574+
575+
<p> - Different data types like Dates and undefined must also be taken into consideration. <p>
576+
577+
<p>Given the above, return a boolean signifying whether a and b are equivalent in content. </p>
578+
579+
__Algorithmic Thinking:__ <p>As we would be comparing each item contained in the objects, a loop may be the first instinct to solving it. However, with the potential of multidimensional iterables, we would have to disect nested arrays in the same way when we encounter them. A combination of iteration and recursion is therefore necessary. So for each item of the array a data type check is necessary as well, to allow execution of a relevant comparison.
580+
581+
Breaking it down:
582+
* check if ```a === b```
583+
* check if ```a``` and ```b``` are both iterable
584+
* iterate over ```a``` using keys and call deepCompare recursively
585+
</p>
569586
570-
__Algorithmic Thinking:__ <p> </p>
571587
588+
__code Implementation:__ <p>
572589
573-
__code Implementation:__ <p> </p>
590+
Firstly, we'll do the most simple check of ```a === b``` to avoid unnecessary complexity. This will process all of the equal literal values for us.
591+
592+
```js
593+
if(a === b) return true
594+
```
595+
596+
Then comes the interesting part! There are several data types we need to look out for: Objects, Arrays(which JS treats as an object), and Dates(which is also treated as an object!), thus all we have to do is check if both a and b are of type object. If not, we can just return false as they didn't pass the ```a === b``` test.
597+
598+
```js
599+
if(typeof a === "object" && typeof b === "object")...
600+
```
601+
602+
Note that we use ```===``` here to differentiate between data types strictly.
603+
604+
Next, we can process the dates first, as that doesn't require iteration. Make sure to compare ```Date.valueOf()``` instead of the date object itself.
605+
606+
```js
607+
if(a instanceof Date && b instanceof Date) return a.valueOf() === b.valueOf()
608+
```
609+
610+
Lastly, by taking the keys of the iterables we can compare the length of ```a``` and ```b```, then make use of built-in Array.some method to check if any values of the two iterables don't match.
611+
612+
```js
613+
//get keys/index of object/array a
614+
const keysA = Object.keys(a)
615+
616+
//make sure a and b are the same length
617+
if(keysA.length !== Object.keys(b).length) return false
618+
619+
//Array.some() iterates through the values in an array and stops executing nested code until there is one that returns true
620+
//in this case that would be when there is one different value between a and b
621+
return !keysA.some( key => {
622+
//run deepCompare recursively
623+
return !deepCompare(a[key], b[key])
624+
})
625+
```
626+
627+
628+
Put it all together, and we have
629+
630+
```js
631+
const deepCompare = (a, b) => {
632+
if(a === b) return true
633+
634+
if(typeof a === "object" && typeof b === "object")
635+
{
636+
if(a instanceof Date && b instanceof Date) return a.valueOf() === b.valueOf()
637+
else
638+
{
639+
const keysA = Object.keys(a)
640+
if(keysA.length !== Object.keys(b).length) return false
641+
return !keysA.some( key => {
642+
return !deepCompare(a[key], b[key])
643+
})
644+
}
645+
}
646+
else return false
647+
}
648+
649+
deepCompare(1, 2)
650+
//false
651+
652+
deepCompare({"first": 1, "second": 2}, {"first": 1, "second": 2})
653+
//true
654+
655+
deepCompare([1, "2", 3.0], [1, "2", 3])
656+
//false
657+
658+
const arr = [1, 2, "3", [{4: "5", 6: 7}, 8.0, new Date(), undefined]]
659+
deepCompare(arr, [1, 2, "3", [{4: "5", 6: 7}, 8.0, new Date(), undefined]])
660+
//true
661+
662+
```
663+
664+
It's that simple! Hope this helps.
665+
</p>
574666
<hr>
575667
<hr>
576668

deepCompare_7/deepCompare.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//deep comparison of multi-dimensional arrays with recursion
2+
3+
const deepCompare = (a, b) => {
4+
if(a === b) return true
5+
6+
if(typeof a === "object" && typeof b === "object")
7+
{
8+
if(a instanceof Date && b instanceof Date) return a.valueOf() === b.valueOf()
9+
else
10+
{
11+
const keysA = Object.keys(a)
12+
if(keysA.length !== Object.keys(b).length) return false
13+
return !keysA.some( key => {
14+
return !deepCompare(a[key], b[key])
15+
})
16+
}
17+
}
18+
else return false
19+
}

0 commit comments

Comments
 (0)