Лучший способ обрезать все элементы объекта рекурсивно? - PullRequest
2 голосов
/ 08 апреля 2020

Если у меня есть такой объект, как

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

Я придумал что-то вроде этого,

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

Но мне интересно, есть ли лучший / более эффективный способ сделать это?

JSFiddle

Ответы [ 3 ]

1 голос
/ 08 апреля 2020

Я бы переключился на массив / объект / другое непосредственно в функции, упрощая рекурсивный вызов:

 const trimFields = (data) =>
    _.isArray(data) 
      ? data.map(trimFields)
      :  _.isObject(data) 
        ? _.mapValues(trimFields)
        : trimText(data);
0 голосов
/ 08 апреля 2020

Я бы написал более общую функцию deepMap и затем вызвал бы ее с trimText и вашим объектом. Затем он становится легко используемым и отделяет обработку навигации по объекту от фактического преобразования поля. Писать несложно, с loda или без sh. Вот одна из версий:

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)
)

Обратите внимание, что я упростил trimText, поскольку trim встроен в String.prototype.

Написание этой универсальной c версии не намного сложнее, чем разовая версия, и вы можете использовать ее для других целей.

deepMap (square) ({a: 1, b: [2, 3, 4], c: [{d: 5}, {d: 6}]})
//=> {a: 1, b: [4, 9, 16], c: [{d: 25}, {d: 36}]}
0 голосов
/ 08 апреля 2020

Функция loda sh _.transform() выполняет итерацию как объектов, так и массивов. Вы можете создать рекурсивную функцию mapValues(), используя _.transform(), а затем применить функцию преобразования (в данном случае _.trim()) для обработки всех значений:

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>
...