點燈坊

失くすものさえない今が強くなるチャンスよ

使用 differenceWith() 對兩個 Array 相減

Sam Xiao's Avatar 2020-08-19

若要對兩個 Array 相減,且想自己提供比較條件,可使用 differenceWith() 處理, 尤其對 Object 比較的是 Value 而不是 Reference。

Version

Ramda 0.27.1

Primitive

import { pipe, differenceWith } from 'ramda'

let a = [1, 2, 3]
let b = [1, 4, 5]

pipe(
  differenceWith((x, y) => x === y, a)
)(b) // ?

difference() 提供的是內定的比較方式,而 differenceWith() 可提供自訂 predicate。

differenceWith()
((a, a) → Boolean) → [a] → [a] → [a]
提供 predicate 對兩個 Array 相減

(a, a) → Boolean:提供自訂 Predicate

[a]:第一個 array

[a]:第二個 array

[a]:回傳相減結果

diff001

Point-free

import { pipe, differenceWith, equals } from 'ramda'

let a = [1, 2, 3]
let b = [1, 4, 5]

pipe(
  differenceWith(equals, a)
)(b) // ?

differnceWith() 的 predicate 也可以使用 equals() 使其 point-free。

事實上 differenceWith(equals) 相當於 difference()

diff002

Object

import { pipe, differenceWith } from 'ramda'

let a = [
  { name: 'Sam' }, 
  { name: 'Kevin' }, 
  { name: 'Jimmy' }
]

let b = [
  { name: 'Kevin' }
]

pipe(
  differenceWith((x, y) => x.name === y.name, a)
)(b) // ?

differenceWith() 可使用自己的 predicate 判斷 Object。

diff003

Point-free

import { pipe, differenceWith, eqProps } from 'ramda'

let a = [
  { name: 'Sam' }, 
  { name: 'Kevin' }, 
  { name: 'Jimmy' }
]

let b = [
  { name: 'Kevin' }
]

pipe(
  differenceWith(eqProps('name'), a)
)(b) // ?

也可使用 eqProps() 產生 predicate 使 differenceWith() 能 point-free。

diff004

Conclusion

  • differenceWith() 可輕易對兩 Array 相減,尤其對於 Object 是比較其 value equality,而不是 reference equality,非常實用
  • differenceWith() 對於 Object,可使用 allPass()eqProps() 使其 Point-free,非常經典

Reference

Ramda, differenceWith()