This is a symmetric difference problem which has 2 mathematical approaches:
-
A Δ B = (A \ B) ⋃ (B \ A)
Which technically means: The symmetric difference is equal to the difference between A and B --in union with-- the difference btween B and A. In code, this approach ensures that we don’t have to get rid of duplicates (since we’re not working with an actual Set data structure that gets rid of duplicates for us) although SOME duplicates may remain if one of the two arrays have duplicate items that may end up in the concatenated result.
-
A Δ B = (A ⋃ B) \ (A ⋂ B)
This means that the symmetric difference is equal to the difference between the union of A and B and the intersection of A and B. In code, this is more or less what most of us campers did when we solved this problem which means:
- Concat A with B,
- Then use filter on the result to get rid of elements present in BOTH A and B.
// Approach 2
A.concat(B)
.filter(item => !(contains(item, A) && contains(item, B)));
// Approach 1
A.filter(item => !contains(item, B))
.concat(
B.filter(item => !contains(item, A))
);
The predicate of approach 2 reads as
NOT (exists in A AND exists in B)
contains
doesn’t exist in JS, so, read the rest of my message to find out exactly how to do it. Also, remember that !
is logical negation, it means “NOT”.
Your predicate (function inside filter) is wrong, first of all, what’s the point of using map/filter/reduce if you’re still using a for loop for indexing purposes? These methods provide a second (and third parameter that references the original array) argument to their callbacks that can be used as an index:
arr.iterativeMethod((item, index, originalArr) => {
// ...
}, thisArg);
Secondly, this hardly matters in this particular case. What you can do instead is make use of the .indexOf
array method that returns the index of an element in the array and if it doesn’t find it, returns -1.
Note that ES7 introduced the .includes
method but that’s another story.
So basically you can implement it as:
/**
* Predicate function that tells you whether
* a particular value is present in an array.
* @param {T} item - The element to find.
* @param {T[]} arr - Where to find it.
* @return {boolean} - The result of the search.
*/
function contains(item, arr) {
return arr.indexOf(item) >= 0;
}