點燈坊

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

使用 innerJoin() 提供自訂條件找出兩 Array 交集部分

Sam Xiao's Avatar 2020-03-28

intersection() 雖可找出兩 array 的 交集,卻無法提供自訂條件,但 innerJoin() 可以。

Version

macOS Catalina 10.15.4
VS Code 1.43.2
Quokka 1.0.284
Ramda 0.27.0

intersection()

import { intersection } from 'ramda'

let data0 = [1, 3, 5, 3]
let data1 = [5, 7, 3, 7]

intersection(data0)(data1) // ?

Ramda 的 intersection 只提供基本的 交集,且結果不重複。

若想自訂 判斷條件 則無法使用 intersection()

join000

innerJoin()

import { innerJoin } from 'ramda'

let data0 = [1, 3, 5, 3]
let data1 = [5, 7, 3, 7]

let f = innerJoin((x, y) => x === y)

f(data0)(data1) // ?

innerJoin() 可自訂 判斷條件 取得交集,但有可能 重複

innerJoin()
((a, b) → Boolean) → [a] → [b] → [a]
可自訂條件取得 array 交集,若符合條件則回傳第一個 argument 的 element

(a, b) -> Boolean:傳入自訂的 判斷條件

[a]:data 為第一個 array

[b]:data 為第二個 array

[a]:回傳在第一個 argument 且在第二個 argument 的 element

join001

import { innerJoin, equals } from 'ramda'

let data0 = [1, 3, 5, 3]
let data1 = [5, 7, 3, 7]

let f = innerJoin(equals)

f(data0)(data1) // ?

innerJoin() 的 callback 可以改用 equals() 使其 point-free。

join002

intersection()

import { innerJoin, equals, uniq, compose, curry } from 'ramda'

let data0 = [1, 3, 5, 3]
let data1 = [5, 7, 3, 7]

let intersection = curry(compose(uniq, innerJoin(equals)))

let f = intersection

f(data0)(data1) // ?

intersection() 也可使用 innerJoin()uniq() 組合而成。

join003

Object

import { innerJoin } from 'ramda'

let data0 = [
  { title: 'FP in JavaScript', price: 100 }
]

let data1 = [
  { title: 'Speaking JavaScript', price: 100 },
  { title: 'FP in JavaScript', price: 200 },
  { title: 'Learning Haskell', price: 300 },
]

let f = innerJoin((x, y) => x.title === y.title)

f(data0)(data1) // ?

若為 object array,則無法簡單使用 intersection(),只能使用 innerJoin() 提供自訂條件。

若我們想 title 相等則視為 object 相等,並希望回傳第一個 array 的 element。

join004

Point-free

import { innerJoin, eqProps } from 'ramda'

let data0 = [
  { title: 'FP in JavaScript', price: 100 }
]

let data1 = [
  { title: 'Speaking JavaScript', price: 100 },
  { title: 'FP in JavaScript', price: 200 },
  { title: 'Learning Haskell', price: 300 },
]

let f = innerJoin(eqProps('title'))

f(data0)(data1) // ?

innerJoin() 的 callback 也可改用 eqProps() 使其 point-free。

join005

Conclusion

  • innerJoin()intersection() 靈活,可提供自訂條件,但不保證結果 不重複,需自行組合 uniq()

Reference

Ramda, innerJoin()
Ramda, intersection()
Ramda, equals()
Ramda, uniq()
Ramda, compose()
Ramda, curry()
Ramda, eqProps()