这是一个类似于How to remove undefined and null values from an object using lodash?的问题。但是,那里提出的解决方案并不保留构造函数。除此之外,我想只删除那些开头的密钥,比如' _'。
这是我正在寻找的东西,似乎无法从lodash获得:
输入:new Cons({key1 : 'value1', key2 : {key21 : 'value21', _key22: undefined}, key3: undefined, _key4 : undefined})
输出:
{key1 : 'value1', key2 : {key21 : 'value21'}, key3: undefined}
例如function Cons(obj){_.extend(this, obj)}
我有一个使用lodash omitBy
的解决方案,但是,我放弃了构造函数信息(即我不能再使用instanceof Cons
来区分对象构造函数)。 forIn
看起来像是递归遍历的一个很好的候选者,但它只为我提供了value
和key
。我还需要路径才能删除对象(使用unset
)。
请注意:
instanceof whatevertheconstructorwas
仍为真是否有更好的解决方案(使用lodash或其他方式)?
答案 0 :(得分:9)
您可以通过使用omitBy()和mapValues()创建一个递归省略键的函数,作为递归遍历键的辅助函数。另请注意,这也支持具有嵌套数组的对象的数组遍历或具有嵌套对象的顶级数组。
function omitByRecursively(value, iteratee) {
var cb = v => omitByRecursively(v, iteratee);
return _.isObject(value)
? _.isArray(value)
? _.map(value, cb)
: _(value).omitBy(iteratee).mapValues(cb).value()
: value;
}
function Cons(obj) {
_.extend(this, omitByRecursively(obj, (v, k) => k[0] === '_'));
}
示例:
function omitByRecursively(value, iteratee) {
var cb = v => omitByRecursively(v, iteratee);
return _.isObject(value)
? _.isArray(value)
? _.map(value, cb)
: _(value).omitBy(iteratee).mapValues(cb).value()
: value;
}
function Cons(obj) {
_.extend(this, omitByRecursively(obj, (v, k) => k[0] === '_'));
}
var result = new Cons({
key1 : 'value1',
key2 : {
key21 : 'value21',
_key22: undefined
},
key3: undefined,
_key4 : undefined,
key5: [
{
_key: 'value xx',
key7: 'value zz',
_key8: 'value aa'
}
]
});
console.log(result);
.as-console-wrapper{min-height:100%;top:0}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.12.0/lodash.js"></script>
<强>更新强>
您可以通过创建一个以each()递归遍历对象的函数并通过unset()结算删除来改变对象本身。
function omitByRecursivelyInPlace(value, iteratee) {
_.each(value, (v, k) => {
if(iteratee(v, k)) {
_.unset(value, k);
} else if(_.isObject(v)) {
omitByRecursivelyInPlace(v, iteratee);
}
});
return value;
}
function Cons(obj){_.extend(this, obj)}
var result = omitByRecursivelyInPlace(instance, (v, k) => k[0] === '_');
function omitByRecursivelyInPlace(value, iteratee) {
_.each(value, (v, k) => {
if(iteratee(v, k)) {
_.unset(value, k);
} else if(_.isObject(v)) {
omitByRecursivelyInPlace(v, iteratee);
}
});
return value;
}
function Cons(obj){_.extend(this, obj)}
var instance = new Cons({
key1 : 'value1',
key2 : {
key21 : 'value21',
_key22: undefined
},
key3: undefined,
_key4 : undefined,
key5: [
{
_key: 'value xx',
key7: 'value zz',
_key8: 'value aa'
}
]
});
var result = omitByRecursivelyInPlace(instance, (v, k) => k[0] === '_');
console.log(result instanceof Cons);
console.log(result);
.as-console-wrapper{min-height:100%;top:0}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.12.0/lodash.js"></script>
答案 1 :(得分:1)
免责声明:我不知道lodash支持哪些内置函数,但使用vanilla javascript可以很容易地实现。
从过滤对象密钥的通用函数开始
// filter obj using function f
// this works just like Array.prototype.filter, except on objects
// f receives (value, key, obj) for each object key
// if f returns true, the key:value appears in the result
// if f returns false, the key:value is skipped
const filterObject = f=> obj=>
Object.keys(obj).reduce((res,k)=>
f(obj[k], k, obj) ? Object.assign(res, {[k]: obj[k]}) : res
, {});
然后是一个根据您的特定行为进行过滤的功能
// filter out keys starting with `_` that have null or undefined values
const filterBadKeys = filterObject((v,k)=> /^[^_]/.test(k) || v !== null && v !== undefined);
然后在对象上调用它
filterBadKeys({a: null, _b: null, _c: undefined, z: 1});
//=> { a: null, z: 1 }
现在可以轻松地将其集成到构造函数中
function Cons(obj) {
_.extend(this, filterBadKeys(obj));
// ...
}
修改强>
第二个想法是,你可以抽象出通用操作并定义一个特定的深度&#34;而不是用隐式深度递归来屠杀一个非常好的函数。过滤功能
const reduceObject = f=> init=> obj=>
Object.keys(obj).reduce((res,k)=> f(res, obj[k], k, obj), init);
// shallow filter
const filterObject = f=>
reduceObject ((res, v, k, obj)=> f(v, k, obj) ? Object.assign(res, {[k]: v}) : res) ({});
// deep filter
const deepFilterObject = f=>
reduceObject ((res, v, k, obj)=> {
if (f(v, k, obj))
if (v && v.constructor === Object)
return Object.assign(res, {[k]: deepFilterObject (f) (v)});
else
return Object.assign(res, {[k]: v});
else
return res;
}) ({});
const filterBadKeys = deepFilterObject((v,k)=> /^[^_]/.test(k) || v !== null && v !== undefined);
filterBadKeys({a: null, _b: null, _c: undefined, _d: { e: 1, _f: null }, z: 2});
//=> { a: null, _d: { e: 1 }, z: 2 }
与构造函数的集成保持不变
function Cons(obj) {
_.extend(this, filterBadKeys(obj));
// ...
}
答案 2 :(得分:1)
您可以使用 rundef
包。
默认情况下,它会将所有顶级属性替换为设置为undefined
的值。但是它支持以下选项:
mutate
- 将其设置为false
以返回您提供的同一对象;这将确保构造函数不会被更改recursive
- 将此设置为true
以递归处理您的对象因此,对于您的用例,您可以运行:
rundef(object, false, true)
答案 3 :(得分:0)
您可以使用JSON.parse()
,RegExp.prototype.test()
,JSON.parse(JSON.stringify(obj, function(a, b) {
if (!/^_/.test(a) && b === undefined) {
return null
}
return /^_/.test(a) && !b ? void 0 : b
}).replace(/null/g, '"undefined"'));
var obj = {key1 : 'value1', key2 : {key21 : 'value21', _key22: undefined}, key3: undefined, _key4 : undefined}
var res = JSON.stringify(obj, function(a, b) {
if (!/^_/.test(a) && b === undefined) {
return null
}
return /^_/.test(a) && !b ? void 0 : b
}).replace(/null/g, '"undefined"');
document.querySelector("pre").textContent = res;
res = JSON.parse(res);
console.log(res)
<pre></pre>
&#13;
for(;;) {
read state of /sys/class/gpio/export/
write the state into a vector<bool>
analyze the bool vector to figure out when the machine is turned on or off (compare against a template vector read from an external txt file)
if the machine just got turned on, cout a message
if the machine just gor turned off, cout a message
}
&#13;
答案 4 :(得分:0)
@ryeballar 的回答基本有效,但我想要三个附加功能:
iteratee
检查,因为在对象上递归之后,它可能应该被省略还借鉴了一些想法:https://codereview.stackexchange.com/a/58279
export function omitByRecursivelyInPlace<T extends object | null | undefined>(value: T, iteratee: (v: any, k: string) => any) {
_.each(value, (v, k) => {
// no longer an if/else
if (_.isObject(v)) {
omitByRecursivelyInPlace(v, iteratee);
}
if (iteratee(v, k)) {
// check for array types
if (_.isArray(value)) _.pullAt(value, [parseInt(k)]);
else _.unset(value, k);
}
});
return value;
}
不确定这里的表现。开放反馈。可能不是 OP 所要求的。
请参阅 https://github.com/lodash/lodash/issues/723 以了解官方 lodash 存储库中有关此主题的讨论。好像不支持。