问题
If I have an object like,
const obj = {
field: {
subfield: {
innerObj: { a: ' asdasd asdas . ' },
innerArr: [' s ', ' ssad . '],
innerArrObj: [ { b: ' adsad ' } ],
}
}
}
I've come up with something like this,
const trimFields = (data) =>
_.mapValues(data, (element, k) =>
_.isArray(element)
? element.map((value) =>
_.isObject(value) ? trimFields(value) : trimText(value)
)
: _.isObject(element)
? trimFields(element)
: trimText(element)
);
But I'm wondering if there is a better / more efficient way to do this?
JSFiddle
回答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);
回答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}]}
回答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>
来源:https://stackoverflow.com/questions/61098396/a-better-way-to-trim-all-elements-in-an-object-recursively