點燈坊

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

使用 zipWith() 將兩個 Array 合併成自訂形式

Sam Xiao's Avatar 2020-01-08

zip() 只能制式的將兩個 Array 合併成 Array Pair,若想將兩個 Array 合併成其他形式則要使用 zipWith()

Version

Ramda 0.27.1

zip()

import { zip } from 'ramda'

let girls = [
  { name: 'Mary' },
  { name: 'Jessie' }
]

let boys = [
  { name: 'John', car: 'BMW' },
  { name: 'Tomy', car: 'TOYOTA' },
  { name: 'Paul', car: 'Benz' }
]

let f = zip

f (girls) (boys) // ?

想將 girlsboys 兩個 Array 合併,直覺會使用 zip()

zip() 只能合併成制式的 Array Pair。

zipwith000

zipWith()

import { zipWith } from 'ramda'

let girls = [
  { name: 'Mary' },
  { name: 'Jessie' }
]

let boys = [
  { name: 'John', car: 'BMW' },
  { name: 'Tomy', car: 'TOYOTA' },
  { name: 'Paul', car: 'Benz' }
]

let f = zipWith ((x, y) => `${x.name}: ${y.car}`)

f (girls) (boys) // ?

若想合併成 Array String,且格式為 name: car,其中 name 來自於 girls,而 car 來自於 boys

對於自訂形式合併,可使用 zipWith() 提供自訂 function。

zipWith()
((a, b) → c) → [a] → [b] → [c]
自行提供 function 的 zip()

((a, b) → c):傳入 function 描述合併方式

[a]:data 為 Array

[b]:data 為 Array

[c]:回傳合併後新 Array

zip() 相當於 zipWith((x, y) => [x, y])

zipwith001

Point-free

import { zipWith, useWith, prop } from 'ramda'
import { formatN } from 'wink-fp'

let girls = [
  { name: 'Mary' },
  { name: 'Jessie' }
]

let boys = [
  { name: 'John', car: 'BMW' },
  { name: 'Tomy', car: 'TOYOTA' },
  { name: 'Paul', car: 'Benz' }
]

let toString = useWith(
  formatN (2) ('{0}: {1}'), [prop ('name'), prop ('car')]
)

let f = zipWith (toString)

f (girls) (boys) // ?

若想進一步將傳入 zipWith() 的 function 也 Point-free,可使用 useWith() 加以組合:

  • formatN (2) ('{0}: {1}'):建立 template string
  • prop ('name'):從 girls 取出 name property
  • prop ('car'):從 boys 取出 car property

zipwith002

Conclusion

  • zipWith() 能自行提供 function,彈性比 zip() 大很多

Reference

Ramda, zipWith()