使用 Lodash 或 Underscore 检查对象是否只有给定的键
Check if object has only the given keys using Lodash or Underscore
是否有 Lodash 或 Underscore 方法可以查找对象是否仅具有该对象的给定键。我想要一个 Lodash 或 Underscore 实现,尽管使用原生 JS 这听起来微不足道。
例如,如果我的对象看起来像并假设有一个名为 hasOnly
的 lodash 方法
const obj = {
name: undefined,
age: 15,
school: 'Some school'
}
_.hasOnly(obj,['name','age']) //return false
_.hasOnly(obj,['name','age','city']) //return false
_.hasOnly(obj,['name','age','school']) //return true
我似乎无法在文档中找到方法
快速而肮脏:
hasOnly = (obj, props) => _.isEqual(_.keys(obj).sort(), props.sort())
排序完成,因为我们正在比较数组。
作为替代方案,可以将 props
和 _.keys(obj)
都变成对象,其中 props
和 _.keys(obj)
是键,而值是虚拟键, 始终相同,例如 1
。这样做的功能可能是这样的:
make1ValuedObj = keys => _.zipObject(keys, Array(keys.length).fill(1))
然后将它们传递给 _.isEqual
而无需对任何内容进行排序:
hasOnly = (obj, props) => _.isEqual(make1ValuedObj(_.keys(obj)), make1ValuedObj(props))
实际情况是,当您构造对象时必须进行某种“排序”,所以我认为与上述解决方案相比并没有真正的优势。
在几乎所有情况下,本机解决方案都会更快:
const obj = {
name: undefined,
age: 15,
school: 'Some school'
}
const hasOnly = (obj,props) => {
var objProps = Object.keys(obj)
return objProps.length == props.length && props.every(p => objProps.includes(p))
}
console.log(hasOnly(obj,['name','age'])) //return false
console.log(hasOnly(obj,['name','age','city'])) //return false
console.log(hasOnly(obj,['name','age','school'])) //return true
将此与使用 lodash 的其他答案进行基准测试表明 lodash 解决方案要慢 95%(在我的机器上)
我认为 Enlico 的回答很好,但为了完整起见,我会提到另一个不需要排序的选项。这是基于直接比较对象而不是比较键数组。
请注意,下面的代码采用原始下划线。对于 Lodash,将 _.mapObject
替换为 _.mapValues
。
// replace all properties by true to prevent costly recursion
const mask = obj => _.mapObject(obj, _.constant(true));
function hasOnly(obj, keys) {
const masked = mask(obj);
// compare obj to a trimmed version of itself
return _.isEqual(masked, _.pick(masked, keys));
}
是否有 Lodash 或 Underscore 方法可以查找对象是否仅具有该对象的给定键。我想要一个 Lodash 或 Underscore 实现,尽管使用原生 JS 这听起来微不足道。
例如,如果我的对象看起来像并假设有一个名为 hasOnly
const obj = {
name: undefined,
age: 15,
school: 'Some school'
}
_.hasOnly(obj,['name','age']) //return false
_.hasOnly(obj,['name','age','city']) //return false
_.hasOnly(obj,['name','age','school']) //return true
我似乎无法在文档中找到方法
快速而肮脏:
hasOnly = (obj, props) => _.isEqual(_.keys(obj).sort(), props.sort())
排序完成,因为我们正在比较数组。
作为替代方案,可以将 props
和 _.keys(obj)
都变成对象,其中 props
和 _.keys(obj)
是键,而值是虚拟键, 始终相同,例如 1
。这样做的功能可能是这样的:
make1ValuedObj = keys => _.zipObject(keys, Array(keys.length).fill(1))
然后将它们传递给 _.isEqual
而无需对任何内容进行排序:
hasOnly = (obj, props) => _.isEqual(make1ValuedObj(_.keys(obj)), make1ValuedObj(props))
实际情况是,当您构造对象时必须进行某种“排序”,所以我认为与上述解决方案相比并没有真正的优势。
在几乎所有情况下,本机解决方案都会更快:
const obj = {
name: undefined,
age: 15,
school: 'Some school'
}
const hasOnly = (obj,props) => {
var objProps = Object.keys(obj)
return objProps.length == props.length && props.every(p => objProps.includes(p))
}
console.log(hasOnly(obj,['name','age'])) //return false
console.log(hasOnly(obj,['name','age','city'])) //return false
console.log(hasOnly(obj,['name','age','school'])) //return true
将此与使用 lodash 的其他答案进行基准测试表明 lodash 解决方案要慢 95%(在我的机器上)
我认为 Enlico 的回答很好,但为了完整起见,我会提到另一个不需要排序的选项。这是基于直接比较对象而不是比较键数组。
请注意,下面的代码采用原始下划线。对于 Lodash,将 _.mapObject
替换为 _.mapValues
。
// replace all properties by true to prevent costly recursion
const mask = obj => _.mapObject(obj, _.constant(true));
function hasOnly(obj, keys) {
const masked = mask(obj);
// compare obj to a trimmed version of itself
return _.isEqual(masked, _.pick(masked, keys));
}