DEV Community

You Might Not Need Lodash

Ant The Developer on March 15, 2018

You can check out more of my tutorials and articles on my main blog. Enjoy the article! While Lodash may have become a staple in any JavaScript de...
Collapse
 
gsonderby profile image
Gert Sønderby • Edited

Extremely quick and dirty homebrew of a flatten function:

const flatten = array => array.reduce(
  (flatArray, item) => {
    if (Array.isArray(item)) {
      return flatArray.concat(flatten(item));
    } else {
      return flatArray.concat([item]);
    }
  },
  []
);

EDITED: Return a fresh array instead of modifying flatArray. Clearer, less prone to nitpickery.

Collapse
 
masaeedu profile image
Asad Saeeduddin

It's a little confusing to simultaneously use reduce and push. Use reduce when you're actually computing a new value, use a for of loop when you're mutating things in a loop.

// Use this
const flattened = as => as.reduce((p, c) => [...p, ...c], [])

// Or this
const flattened = []
for (const item of as) {
  flattened.push(...item)
}
Collapse
 
gsonderby profile image
Gert Sønderby

Your first example chokes on [1,[2,3,[4]],5,[6,7]], throwing an error. Worse, on ['yo',['dawg','I',['herd']],'you',['like','arrays']] it breaks in a number of interesting ways, spreading some strings, failing to spread some arrays.

Thread Thread
 
masaeedu profile image
Asad Saeeduddin

It is an implementation of the join function for arrays, and works with arrays of arrays, not arrays of mixed objects.

If you need it to work with mixed objects you'll need a recursive call (or ap+pure):

const flattened = as => as.reduce((p, c) => [...p, ...(Array.isArray(c) ? flattened(c) : [c])], [])

Anyway, the point is to avoid mutation in the reduce, whatever it is you may be implementing.

Thread Thread
 
gsonderby profile image
Gert Sønderby

At this point it honestly seems like you're just trying to score points against me, in some way. I am disinterested in continuing that.

Thread Thread
 
masaeedu profile image
Asad Saeeduddin

Sorry to hear you feel that way. I was just suggesting that using mutation in reduce is confusing, didn't mean for it to turn into this long-running back and forth.

Collapse
 
mlg profile image
m-lg

Quick way to flatten 1 deep
const feed = [].concat(...sourceArray)

Collapse
 
nicolasnarvaez profile image
Nicolás Narváez

i do the same ;)

Collapse
 
antjanus profile image
Ant The Developer

wow. That's awesome! It took me a few to figure out how this works.

Collapse
 
paulasantamaria profile image
Paula Santamaría

Great article! Whenever I feel like I need to add Lodash to a new project I try to solve my immediate needs with plain Javascript first. Turns out most of the times that's enough.
It's an awesome library, but I like to keep my projects as simple as possible.

Collapse
 
stevealee profile image
SteveALee

You can also use mutlple sources in the RHS of a spead expression to get a merge

Collapse
 
antjanus profile image
Ant The Developer • Edited

do you mean like this?

const mergedObj = { ...obj1, ...obj2 };

My only issue with it is that it doesn't recursively merge. It's fine for flat objects. I use this pattern pretty often at work, sometimes in conjunction with lodash.

For instance, I use Objection for ORM and it has "computed properties" that need to be accessed in order to get the value, they're not serialized when doing toJSON so I often resort to:

res.send({ ...someModel, ..._.pick(someModel, ['computedProperty1', 'computedProp2']);

EDIT Totally forgot, this is a pretty common pattern in Redux!

Collapse
 
stevealee profile image
SteveALee

Completely agree. Its shallow like Object.assign. I was just say is an alternative to it really.

Collapse
 
whiteadi profile image
Adrian Albu