點燈坊

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

使用 join() 將 Array 轉成 String

Sam Xiao's Avatar 2020-01-26

Array 與 String 都是常用型別,Ramda 提供了 join() 能將 Array 轉成 String。

Version

macOS Catalina 10.15.2
VS Code 1.41.1
Quokka 1.0.274
Ramda 0.26.1

Imperative

let data = [1, 2, 3]

let join = separator => arr => {
  let result = ''

  for(let i = 0; i < arr.length; i++) {
    if (i === arr.length - 1)
      result += arr[i]
    else
      result += arr[i] + separator
  }

  return result
}

join(',')(data) // ?

join() 除了能將 string 轉成 array 外,還可傳入 separator 將 element 隔離。

Imparative 會使用 for loop,若不是最後一個 element 則加入 separator。

join000

reduce()

let data = [1, 2, 3]

let join = separator => arr => arr.reduce((a, x, i) => 
  i === arr.length - 1 ? a + x : a + x + separator
, '')

join(',')(data) // ?

也可將 imperative 使用 reduce() 改寫之。

join001

Functional

import { reduce, pipe, map, flatten, dropLast, toString } from 'ramda'

let data = [1, 2, 3]

let join = separator => pipe(
  map(toString),
  map(x => [x, separator]),
  flatten,
  dropLast(1),
  reduce((a, x) => a + x, '')
)

join(',')(data) // ?

Functional 會使用以下步驟解決問題:

  • 使用 map(toString) 將 element 由 number 轉成 array
  • 使用 map(x => [x, separator]) 加上 separator,此時為兩層 array
  • 使用 flatten() 將兩層 array 攤平
  • 使用 dropLast(1) 將最後一個 separator 刪除
  • 使用 reduce((a, x) => a + x, '') 將 array 轉成 string

join002

init()

import { reduce, pipe, map, flatten, init, toString } from 'ramda'

let data = [1, 2, 3]

let join = separator => pipe(
  map(toString),
  map(x => [x, separator]),
  flatten,
  init,
  reduce((a, x) => a + x, '')
)

join(',')(data) // ?

dropLast(1) 也可用 init() 加以取代。

join007

chain()

import { reduce, pipe, chain, init, map, toString } from 'ramda'

let data = [1, 2, 3]

let join = separator => pipe(
  map(toString),
  chain(x => [x, separator]),
  init,
  reduce((a, x) => a + x, '')
)

join(',')(data) // ?

map()flatten() 可由 chain() 取代。

join003

Point-free

import { reduce, pipe, chain, init, concat, pair, __, map, toString } from 'ramda'

let data = [1, 2, 3]

let join = separator => pipe(
  map(toString),
  chain(pair(__, separator)),
  init,
  reduce(concat, '')
)

join(',')(data) // ?

可將 chain()reduce() 加以 point-free,改以 function 產生。

join004

invoker

import { invoker } from 'ramda'

let data = [1, 2, 3]

let join = invoker(1)('join')

join(',')(data) // ?

其實 ECMAScript 已經內建 Array.prototype.join(),因此可借用 invoker() 轉成 join() 即可。

join005

Ramda

import { join } from 'ramda'

let data = [1, 2, 3]

join(',')(data) // ?

Ramda 已經內建 join() 可直接使用。

join()
String → [a] → String
將 array 轉成 string,可另外提供 separator

String:傳入 element 間的 separator,不包含最後一筆

[a]:data 為 array

String:回傳為 string

join006

Conclusion

  • 若只想將 array 轉成 string,可將 separator 傳 empty string 即可
  • invoker() 相當實用,可將 ECMAScript prototype 的 method 轉成 function

Reference

Ramda, join()