點燈坊

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

使用 entries() 同時回傳 Index 與 Element 的 Pair Array

Sam Xiao's Avatar 2020-11-27

ECMAScript 2015 迎來了 Array.prototype.entries(),可同時回傳 Array 的 Index 與 Element,但其回傳為 Array Iterator,使用上較為不便,可自行組合 entries() 改回傳 Array,方便以 Function Pipline 組合其他 Function 。

Version

Wink-fp 1.20.38

Array.prototype.entries()

let data = [
  'FP in JavaScript', 
  'Get Programming with Haskell', 
  'Speaking JavaScript'
]

let f = a => {
  let result = []
  let items = a.entries()
  
  for (let [k, v] of items)
    result.push(`${k}: ${v}`)

  return result
}

f(data) // ?

由於 Array.prototype.entries() 回傳為 Array Iterator,因此可使用 for loop,由於每個 item 為 Array,可再使用 array destructuring 分解出 kv

entries000

entries()

import { pipe, map } from 'ramda'

let data = [
  'FP in JavaScript', 
  'Get Programming with Haskell', 
  'Speaking JavaScript'
]

let entries = a => a.map((v, k) => [k, v])

pipe(
  entries,
  map(([k, v]) => `${k}: ${v}`)
)(data) // ?

由於 Array.prototype.entries() 回傳為 Array Iterator,只能使用 for loop,要使用 Function Pipeline 較不方便,因此我們想自行組合 entries()

第 9 行

let entries = a => a.map((v, k) => [k, v])

使用 map() 回傳 Nested Array。

11 行

pipe(
  entries,
  map(([k, v]) => `${k}: ${v}`)
)(data) // ?

由於 entries() 回傳為 Array,方便與其他 function 做 Function Pipeline。

entries001

Point-free

import { pipe, addIndex, map, pair, flip } from 'ramda'

let data = [
  'FP in JavaScript', 
  'Get Programming with Haskell', 
  'Speaking JavaScript'
]

let entries = addIndex(map)(flip(pair))

pipe(
  entries,
  map(([k, v]) => `${k}: ${v}`)
)(data) // ?

第 9 行

let entries = addIndex(map)(flip(pair))
  • 也可改用 addIndex()map() 先組合出其 callback 帶有 index 的新 map()
  • 再使用 flip(pair) 組合出 Pair Array

entries002

Wink-fp

import { pipe, map } from 'ramda'
import { entries } from 'wink-fp'

let data = [
  'FP in JavaScript', 
  'Get Programming with Haskell', 
  'Speaking JavaScript'
]

pipe(
  entries,
  map(([k, v]) => `${k}: ${v}`)
)(data) // ?

Wink-fp 已經提供 entries() 可直接使用。

entries()
[a] -> [[k, v]]
回傳以 Array 的 key 與 value 所構成的 Nested Array

entries003

Conclusion

  • ES6 的 Array.prototype.entries() 雖有創意,但回傳 Array Iterator 並不好用,只能使用 for loop 搭配 Imperative 寫法
  • 透過自行組合的 entries() 回傳 Nested Array 後,就能搭配其他 function 做 Function Pipeline

Reference

MDN, Array.entries()