0
\$\begingroup\$

I have two large arrays of objects, which look something like:

[
  { key: "prop", Email: "[email protected]" },
  //...
]

and

[
  { key: "prop", "AN EMAIL": "SomeEmail@emailcom" },
  //...
]

To compare the array of objects by email, I first map the arrays to only grab the emails, then I format the emails as follows:

const formatEmail = email => String(email).toLowerCase().replace(/\W/g, "");
const emails1 = objects1.map(o => formatEmail(o.Email));
const emails2 = objects2.map(o => formatEmail(o["AN EMAIL"]));
//... comparison code follows

However I was thinking of instead doing this as follows:

const formatEmail = email => String(email).toLowerCase().replace(/\W/g, "");
const emails1 = objects1.map(o => o.Email).map(formatEmail);
const emails2 = objects2.map(o => o["AN EMAIL"]).map(formatEmail);
//... comparison code follows

I feel the second way is more readable, and there is not a significant performance difference in my use case. I would love feedback on this small exert from my project, and a reasoning of which way is better. Any feedback is appreciated. I did use generic naming for this example.

For context of the use case for this code, the main reason I am writing this script is that we have lots of data that only partially matches in each system. This is usually due to human error on repeating data entry. I can run reports on each system and turn the data into objects to compare in javascript, and am building some logic that will attempt to draw a connection between the two objects based on their emails.

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

I also prefer the second example, due to the functional programming style. I believe it's easier to read because you've decoupled the getter from the transformation.

The only change I'm tempted with is to pull out and share the getter logic with some currying. Something like this:

const emailGetter = key => o => o[key];

const emails1 = objects1.map(emailGetter('Email')).map(formatEmail);
const emails2 = objects2.map(emailGetter('AN EMAIL')).map(formatEmail);

If however, you have a preference for the point free function approach, like you did for map(formatEmail), then this may be more fitting:

const emailGetter = key => o => o[key];
const o1Getter = emailGetter('Email');
const o2Getter = emailGetter('AN EMAIL');

const emails1 = objects1.map(o1Getter).map(formatEmail);
const emails2 = objects2.map(o2Getter).map(formatEmail);

The compromise being a higher setup fee for a cleaner call site.

\$\endgroup\$
3
  • 2
    \$\begingroup\$ I love the second example- how beautiful. I didn't even think about a getter. It might take a few more lines of code, but it feels consistent. I think the biggest issue I have with my example is it doesn't feel consistent. Thanks for your input 👍 \$\endgroup\$ Dec 1, 2021 at 18:39
  • 3
    \$\begingroup\$ Y'all are about 3 neuron impulses away from saying currying \$\endgroup\$
    – radarbob
    Dec 2, 2021 at 16:33
  • 1
    \$\begingroup\$ @radarbob you're right! I've edited to explictly call it out. I hope that's what you meant :) \$\endgroup\$
    – pjlangley
    Dec 2, 2021 at 16:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.