简体   繁体   English

检查 object 是否只有使用 Lodash 或 Underscore 的给定键

[英]Check if object has only the given keys using Lodash or Underscore

Is there a Lodash or Underscore method which can find if an object has only the given keys of that object.是否有 Lodash 或 Underscore 方法可以查找 object 是否仅具有该 object 的给定键。 I would like a Lodash or Underscore implementation even though this sounds trivial using native JS.我想要一个 Lodash 或 Underscore 实现,即使这听起来使用原生 JS 微不足道。

For example if my object looks like and assuming there is a lodash method named hasOnly例如,如果我的 object 看起来像并假设有一个名为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

I couldn't seem to find a way in the docs我似乎无法在文档中找到方法

Quick and dirty:又快又脏:

hasOnly = (obj, props) => _.isEqual(_.keys(obj).sort(), props.sort())

The sorting is done because we are comparing arrays.排序完成是因为我们正在比较 arrays。

As an alternative, one could turn both props and _.keys(obj) into objects where the props and _.keys(obj) are the keys, whereas the value is a dummy one, always the same, such as 1 .作为一种替代方法,可以将props_.keys(obj)都转换为对象,其中props_.keys(obj)是键,而值是虚拟的,始终相同,例如1 The function to do so could be something like this:这样做的 function 可能是这样的:

make1ValuedObj = keys => _.zipObject(keys, Array(keys.length).fill(1))

Then one would pass those to _.isEqual without having to sort anything:然后将它们传递给_.isEqual ,而无需对任何东西进行排序:

hasOnly = (obj, props) => _.isEqual(make1ValuedObj(_.keys(obj)), make1ValuedObj(props))

The reality is that a kind of "sorting" has to happen when you construct the objects, so I don't think there's a real advantage over the solution above.现实情况是,当您构造对象时,必须进行一种“排序”,因此我认为与上述解决方案相比没有真正的优势。

The native solution will be faster in almost all cases:在几乎所有情况下,本机解决方案都会更快:

 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

Benchmarking this against the other answer using lodash shows the lodash solution to be 95% slower (on my machine)使用 lodash 将其与其他答案进行基准测试显示 lodash 解决方案要慢 95%(在我的机器上)

Benchmarks: https://jsbench.me/r9kz2mwr9c/1基准测试: https://jsbench.me/r9kz2mwr9c/1

I think Enlico's answer is fine, but for completeness I'll mention another option which doesn't require sorting.我认为 Enlico 的回答很好,但为了完整起见,我会提到另一个不需要排序的选项。 This is based on comparing objects directy instead of comparing arrays of keys.这是基于直接比较对象而不是比较键的 arrays。

Note that the code below assumes the original Underscore.请注意,下面的代码假定原始下划线。 For Lodash, replace _.mapObject by _.mapValues .对于 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));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM