Given this JSON object, how does lodash remove the reach value from the objects?
{
total: 350,
SN1: {
reach: 200,
engagementRate: 1.35
},
SN2: {
reach: 150,
engagementRate: 1.19
}
}
I've been trying to iteratively remove() it but I always get an undefined object in return so I'm positive I'm doing it wrong. This is also the first time I'm using lodash, so that might be the actual problem.
Can anyone help?
_.transform() the object to another object, and while passing the values to the new object, check if the value is an object and if it has the 'reach' property, and if so use _.omit() to get a new object without reach:
var obj = {
total: 350,
SN1: {
reach: 200,
engagementRate: 1.35
},
SN2: {
reach: 150,
engagementRate: 1.19
}
};
var result = _.transform(obj, function(result, value, key) {
result[key] = _.isObject(value) && `reach` in value ? _.omit(value, 'reach') : value;
});
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>
And if you need a recursive solution that will handle multiple nested object levels, here is deepOmit, which uses the same idea, but without _.omit, and can be used to remove multiple keys (see comments in code):
var obj = {
total: 350,
SN1: {
reach: 200,
engagementRate: 1.35,
DEEP_SN1: {
reach: 200,
engagementRate: 1.35
}
},
SN2: {
reach: 150,
engagementRate: 1.19
}
};
function deepOmit(obj, keysToOmit) {
var keysToOmitIndex = _.keyBy(Array.isArray(keysToOmit) ? keysToOmit : [keysToOmit] ); // create an index object of the keys that should be omitted
function omitFromObject(obj) { // the inner function which will be called recursivley
return _.transform(obj, function(result, value, key) { // transform to a new object
if (key in keysToOmitIndex) { // if the key is in the index skip it
return;
}
result[key] = _.isObject(value) ? omitFromObject(value) : value; // if the key is an object run it through the inner function - omitFromObject
})
}
return omitFromObject(obj); // return the inner function result
}
console.log(deepOmit(obj, 'reach')); // you can use a string for a single value
console.log(deepOmit(obj, ['reach', 'engagementRate'])); // you can use an array of strings for multiple values
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>
There doesn't seem to be a deep omit, but you could iterate over all the keys in the object, and delete reach from the nested objects, recursively:
function omitDeep(obj) {
_.forIn(obj, function(value, key) {
if (_.isObject(value)) {
omitDeep(value);
} else if (key === 'reach') {
delete obj[key];
}
});
}
var obj = {
total: 350,
SN1: {
reach: 200,
engagementRate: 1.35
},
SN2: {
reach: 150,
engagementRate: 1.19
}
};
function omitDeep(obj) {
_.forIn(obj, function(value, key) {
if (_.isObject(value)) {
omitDeep(value);
} else if (key === 'reach') {
delete obj[key];
}
});
}
omitDeep(obj)
console.log(obj);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>
_.mapValues(object, v => _.isObject(v)? _.omit(v, 'reach'): v)
_.mapValues(object, [iteratee=_.identity])Creates an object with the same keys as object and values generated by running each own enumerable string keyed property of
objectthruiteratee. The iteratee is invoked with three arguments: (value, key, object).
_.omit(object, [props])creates an object composed of the own and inherited enumerable string keyed properties of
objectthat are not omitted.
use _.mixin to extend a omitDeep method:
_.mixin({
'omitDeep': function(obj, predicate) {
return _.transform(obj, function(result, value, key) {
if (_.isObject(value)) {
value = _.omitDeep(value, predicate);
}
var doOmit = predicate(value, key);
if (!doOmit) {
_.isArray(obj) ? result.push(value) : result[key] = value;
}
});
}
});
var my = {
"key1": {
"key2": {
"key3": [null, {
"key4": "string",
"key5": true,
"key6": null,
"key7": 8,
"key7": undefined
}, null]
}
}
};
console.log(my);
console.log("omit null:", _.omitDeep(my, _.isNull));
console.log("omit undefined:", _.omitDeep(my, _.isUndefined));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
Recursively omit keys from an object by defining an array of exclude keys in ES6 + Typescript.
omitDeep(myObject, [omitKey1, omitKey2, ...omitKeyN])
// omitDeep.ts
/**
* Recursively remove keys from an object
* @usage
*
* const input = {
* id: 1,
* __typename: '123',
* createdAt: '1020209',
* address: {
* id: 1,
* __typename: '123',
* },
* variants: [
* 20,
* {
* id: 22,
* title: 'hello world',
* __typename: '123',
* createdAt: '1020209',
* variantOption: {
* id: 1,
* __typename: '123',
* },
* },
* {
* id: 32,
* __typename: '123',
* createdAt: '1020209',
* },
* ],
* }
*
* const output = {
* id: 1,
* address: {
* id: 1,
* },
* variants: [
* 20,
* {
* id: 22,
* title: 'hello world',
* variantOption: {
* id: 1,
* },
* },
* {
* id: 32,
* },
* ],
* }
*
* expect(omitDeep(input, ['createdAt, 'updatedAt', __typename']).to.deep.equal(output) // true
*
* @param {object} input
* @param {Array<number | string>>} excludes
* @return {object}
*/
const omitDeep = (input: object, excludes: Array<number | string>): object => {
return Object.entries(input).reduce((nextInput, [key, value]) => {
const shouldExclude = excludes.includes(key)
if (shouldExclude) return nextInput
if (Array.isArray(value)) {
const arrValue = value
const nextValue = arrValue.map((arrItem) => {
if (typeof arrItem === 'object') {
return omitDeep(arrItem, excludes)
}
return arrItem
})
nextInput[key] = nextValue
return nextInput
} else if (typeof value === 'object') {
nextInput[key] = omitDeep(value, excludes)
return nextInput
}
nextInput[key] = value
return nextInput
}, {})
}
export default omitDeep
来源:https://stackoverflow.com/questions/39085399/lodash-remove-items-recursively