比较 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>
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>