比较 ramda.js 中的部分对象

Comparing partial objects in ramda.js

Ramdajs 中有一个 equals 函数非常棒,它将提供以下内容:

// (1) true
R.equals({ id: 3}, { id: 3})

// (2) true
R.equals({ id: 3, name: 'freddy'}, { id: 3, name: 'freddy'})

// (3) false
R.equals({ id: 3, name: 'freddy'}, { id: 3, name: 'freddy', additional: 'item'});

我将如何着手增强此功能,或以其他方式为数字 3

生成 true 结果

我想忽略 rValue 的所有属性 不存在于 lValue 中,但忠实地比较其余部分。我希望 equals 的递归性质保持不变 - 如果可能的话。

我做了一个简单的 fiddle 来显示上面的结果。

我之前没有用过Ramda.js,所以如果我的回答有什么不对的地方,请随时指出。

学习了Ramda.js

的源码

src/equals.js中,是您使用的函数定义的地方。

var _curry2 = require('./internal/_curry2');
var _equals = require('./internal/_equals');

module.exports = _curry2(function equals(a, b) {
  return _equals(a, b, [], []);
});

所以它简单地将函数equals(内部称为_equals)放入"curry"。

所以让我们检查一下内部 _equals 函数,它确实检查了行 84~86:

中的长度
if (keysA.length !== keys(b).length) {
  return false;
}

只需注释这些行即可true如您所愿。


您可以 1) 在 Ramda 的分布式版本中注释这 3 行,或者 2) 您可以向其中添加自己的 partialEquals 函数,然后重新构建并创建您的 Ramda 版本(更推荐,来自我的观点看法)。如果您需要任何帮助,请随时与我讨论。 :)

这也可以通过whereEq

来完成
R.findIndex(R.whereEq({id:3}))([{id:9}{id:8}{id:3}{id:7}])

equals 有一个约束条件,以便与需要 equals(a, b) === equals(b, a) 对称性的 Fantasy Land 规范很好地配合使用,因此为了满足您的情况,我们需要获取对象变成一些等效的形状以供比较。

我们可以通过创建第二个对象的新版本来实现这一点,该版本删除了第一个对象中不存在的所有属性。

const intersectObj = (a, b) => pick(keys(a), b)

// or if you prefer the point-free edition
const intersectObj_ = useWith(pick, [keys, identity])

const a = { id: 3, name: 'freddy' },
      b = { id: 3, name: 'freddy', additional: 'item'}

intersectObj(a, b) // {"id": 3, "name": "freddy"}

使用这个,我们现在可以根据第一个对象中存在的属性比较两个对象 a

const partialEq = (a, b) => equals(a, intersectObj(a, b))

// again, if you prefer it point-free
const partialEq_ = converge(equals, [identity, intersectObj])

partialEq({ id: 3, person: { name: 'freddy' } },
          { id: 3, person: { name: 'freddy' }, additional: 'item'})
//=> true

partialEq({ id: 3, person: { name: 'freddy' } },
          { id: 3, person: { age: 15 }, additional: 'item'})
//=> false

使用whereEq

来自文档:"Takes a spec object and a test object; returns true if the test satisfies the spec, false otherwise."

whereEq({ id: 3, name: 'freddy' }, { id: 3, name: 'freddy', additional: 'item' })

另一种方法是开发自己的版本。归结为:

if (is object):
  check all keys - recursive
otherwise:
  compare using `equals`

这是处理深层对象、数组和非对象值的递归无点版本。

const { equals, identity, ifElse, is, mapObjIndexed, useWith, where } = R

const partialEquals = ifElse(
  is(Object),
  useWith(where, [
    mapObjIndexed(x => partialEquals(x)),
    identity,
  ]),
  equals,
)

console.log(partialEquals({ id: 3 }, { id: 3 }))
console.log(partialEquals({ id: 3, name: 'freddy' }, { id: 3, name: 'freddy' }))
console.log(partialEquals({ id: 3, name: 'freddy' }, { id: 3, name: 'freddy', additional: 'item' }))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>