I'm trying to practice functional programing using JavaScript. These pure functions just work together to find the difference between two arrays. I know that this might be an impractical example of functional programing, but could you let me know where I can improve or maybe where I've misunderstood an FP technique?
"use strict";
let find = (arr1) => (arr2) => {
let diff1 = findDiff(arr1)(arr2);
let diff2 = findDiff(arr2)(arr1);
return concat(diff1)(diff2);
};
let concat = (arr1) => (arr2) => arr1.concat(arr2);
let findDiff = (arr1) => (arr2) => arr1.filter( (elem) => arr2.indexOf(elem) < 0 );
let sweet = find( [1,2,3,4,5] )( [1,2,3,5,6] );
console.log(sweet);
2 Answers 2
I am concerned that you really haven't defined "difference" here and that perhaps your code does not perform the way you expect.
You example is quite simple in that you would expect [4, 6]
. But what if you had arrays like:
[1, 1, 2, 2, 3, 3, 4, 4, 5, 5]
[1, 2, 3, 5, 6]
What do you expect to be returned? Currently, your function would return [4, 4, 6]
, but is that what you expect, or would each instance of a repeated value need to be treated differently (i.e. return would be [1, 2, 3, 4, 4, 5, 6]
)?
Have you considered flipping your array values into object keys (if type conversion is not a concern) or using Array.sort()
on input arrays in combination with fromIndex
parameter to Array.indexOf()
to minimize array iteration caused by Array.indexOf()
? This may not be a concern if you don't expect to be diffing large arrays.
Do you really want to support the find()()
syntax for this? I don't really see much value in nesting your function calls in this manner vs. just using:
let find = (arr1, arr2) => {
// function logic
}
You are not ever returning the intermediate function for possible use elsewhere, so I don't follow the need for this approach.
I agree with the comment from @GregBurghardt around not unneccesarily wrapping native array functions.
I don't like the function being called find
. Perhaps something more descriptive to what is actually happening here like arrayDiff()
. You are not find
ing here at all.
To me this whole thing would be clearer/simpler like this:
let arrayDiff = (arr1, arr2) => {
return arr1.filter( elem => arr2.indexOf(elem) < 0 )
.concat(
arr2.filter( elem => arr1.indexOf(elem) < 0 )
);
};
Note, this obviously does not address some of the questions I asked about uniqueness of array values or optimization of the filter operations.
-
\$\begingroup\$ Thanks for the insights. Again I'm just diving into fp. I agree with you and @GregBurghardt about wrapping concat(I don't know why I did that). Thanks gents! \$\endgroup\$Joseph Palomino– Joseph Palomino2017年03月21日 19:23:56 +00:00Commented Mar 21, 2017 at 19:23
Things look fine actually, except the concat
function. The problem here is the word "concat" because two things can be commonly concatenated in JavaScript: Strings and Arrays.
The only suggestion I would make is not create a functional wrapper around native functionality.
let find = (arr1) => (arr2) => {
// ...
return diff1.concat(diff2);
}
That's a lot easier to read and understand.
Explore related questions
See similar questions with these tags.