Skip to content Skip to sidebar Skip to footer

A Better Way To Trim All Elements In An Object Recursively?

If I have an object like, const obj = { field: { subfield: { innerObj: { a: ' asdasd asdas . ' }, innerArr: [' s ', ' ssad . '],

Solution 1:

I'd switch for array / object / other directly in the function, simplifying the recursive call:

 const trimFields = (data) =>
    _.isArray(data) 
      ? data.map(trimFields)
      :  _.isObject(data) 
        ? _.mapValues(trimFields)
        : trimText(data);

Solution 2:

I would write a more general deepMap function and then call it with trimText and your object. It then becomes easily reusable, and it separates out the handling of object navigation from your actual field transformation. It's not hard to write, either with or without lodash. Here's one version:

const deepMap = (fn) => (obj) => 
  Array .isArray (obj) 
    ? obj .map (deepMap (fn))
  : Object (obj) === obj
    ? Object .fromEntries (Object .entries (obj) .map (([k, v]) => [k, deepMap (fn) (v)]))
  : // else 
    fn (obj)

const trimText = field => typeof field === 'string' ? field .trim () : field;

const obj = {field: {subfield: {innerObj: { a: ' asdasd  asdas . ' }, innerArr: ['  s  ', '  ssad . '], innerArrObj: [ { b: '   adsad  ' } ]}}}

console .log (
  deepMap (trimText) (obj)
)

Note that I simplified trimText, since trim is built into String.prototype.

Writing this generic version is pretty much no more difficult than a one-off version, and you can reuse it for other purposes.

deepMap (square) ({a: 1, b: [2, 3, 4], c: [{d: 5}, {d: 6}]})
//=> {a: 1, b: [4, 9, 16], c: [{d: 25}, {d: 36}]}

Solution 3:

The lodash's _.transform() function iterates both objects and arrays. You can create a recursive mapValues() function using _.transform(), and then apply a transformer function (_.trim() in this case) to handle all values:

const recursiveMapValues = _.curry((fn, obj) => 
  _.transform(obj, (acc, value, key) => {
      acc[key] = _.isObject(value) ?
        recursiveMapValues(fn, value)
        :
        fn(value)
  }))
  
const trimFields = recursiveMapValues(v => _.isString(v) ? _.trim(v) : v)

const obj = {"field":{"subfield":{"innerObj":{"a":" asdasd  asdas . "},"innerArr":["  s  ","  ssad . ", 3],"innerArrObj":[{"b":"   adsad  "}]}}}

const result = trimFields(obj)

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.js"></script>

Post a Comment for "A Better Way To Trim All Elements In An Object Recursively?"