Ramda,测试具有多个谓词的两个对象是否相等

Ramda, test two objects with multiple predicates for props equality

我有两个具有相同道具的对象。我创建了几个谓词来根据业务逻辑测试它们:

const eqId = eqProps('equipmentId');
const eqQuantity = eqProps('quantity');
const eqColor = eqProps('color');

每个谓词接受 (o1, o2) 作为参数。我正在寻找一种更好的方法来根据所有谓词传递输出单个值...换句话说:

predicates.every(predicate => predicate(o1, o2) === true)

但采用更 ramda 风格。 allPass 几乎可以工作,但它只接受一个对象。 我知道我可以用 every 做到这一点,但这个问题是为了帮助我了解更多如何组合函数。

我们需要嵌套 R.allPassR.all 因为它是一个类似矩阵的问题

const a = { suit: '♠︎', rank: '4' };
const b = { suit: '♠︎', rank: '9' };


const isSpade = R.propEq('suit', '♠︎');
const isCard = R.has('suit');

const compareWith = R.pipe(
  R.allPass,
  R.all,
  R.unapply,
);

const isASpadeCard = compareWith([isSpade, isCard])

console.log(
  isASpadeCard(a, b),
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.js" integrity="sha512-3sdB9mAxNh2MIo6YkY05uY1qjkywAlDfCf5u1cSotv6k9CZUSyHVf4BJSpTYgla+YHLaHG8LUpqV7MHctlYzlw==" crossorigin="anonymous"></script>

[...] allPass almost works but it accepts only a single object

也许我不是 100% 理解,但我认为那不是真的。文档说:

The function returned is a curried function whose arity matches that of the highest-arity predicate.

所以给定 eqProps('foo') returns 一个二元函数那么 allPass 返回的函数也将是一个二元函数:

const check = allPass([eqProps('lunch'), eqProps('at')]);

check({lunch: '', at: '1pm'}, {lunch: '', at: '2pm'});
//=> false

check({lunch: '', at: '1pm'}, {lunch: '', at: '1pm'});
//=> true

如果您对对象的外观有一个“蓝图”,那么我发现 eqBy(whereEq) 更容易看清。

eqBy 最好用一个例子来说明。希望这不需要进一步解释:

const streqi = eqBy(toLower); // case insensitive equality

streqi("Foo", "fOO");
//=> true

所以回到eqBy(whereEq)

const check = eqBy(whereEq({lunch: '', at: '1pm'}))

check({lunch: '', at: '1pm', name: 'john'}, {lunch: '', at: '1pm', name: 'tom'});
//=> true

check({lunch: '', at: '1pm', name: 'john'}, {lunch: '', at: '2pm', name: 'tom'});
//                      ^                                       ^
//=> false