依照 spec object 建立新 object

Ramda 之 pick() 只能擷取 Object 的部分 Property,且名稱不能改變,若連名稱也要改變,就要改用 applySpec()

Version


WebStorm 2018.3.3
Quokka 1.0.136
Ramda 0.26.1

Imperative


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const data = [
{ id: 1, title: 'Functional Programming in JavaScript', year: 2016 },
{ id: 2, title: 'RxJS in Action', year: 2017 },
{ id: 3, title: 'Speaking JavaScript', year: 2014 },
];

const getBooks = data => {
let result = [];
for(let x of data)
result.push({ name: x.title, since: x.year });

return result;
};

console.dir(getBooks(data));

Imperative 會使用 for loop,先建立新的 result array,將 title 改成 name,將 year 改成 since, 最後 push 進 result 回傳。

spec002

Array.prototype


1
2
3
4
5
6
7
8
const data = [
{ id: 1, title: 'Functional Programming in JavaScript', year: 2016 },
{ id: 2, title: 'RxJS in Action', year: 2017 },
{ id: 3, title: 'Speaking JavaScript', year: 2014 },
];

const getBooks = data => data.map(x => ({ name: x.title, since: x.year }));
console.dir(getBooks(data));

ECMAScript 的 Array.prototype 也內建 map(),可直接使用 Arrow Function 傳入 callback。

我們只要 titleyear 兩個 property,但名稱要改成 namesince,可直接使用 Arrow Function 指定新的 property 名稱。

因為 map() 因為是 data array 的 method,因此 getBooks() 一定要傳入 data,且 callback 也還有 x 參數,所以並不是 Point-free。

spec000

applySpec()


1
2
3
4
5
6
7
8
9
10
11
12
13
import { map, applySpec, prop } from 'ramda';

const data = [
{ id: 1, title: 'Functional Programming in JavaScript', year: 2016 },
{ id: 2, title: 'RxJS in Action', year: 2017 },
{ id: 3, title: 'Speaking JavaScript', year: 2014 },
];

const getBooks = map(applySpec({
name: prop('title'),
since: prop('year'),
}));
console.dir(getBooks(data));

Ramda 提供了 applySpec(),用來建立新 object,並使用 prop() 取得原 object 的 property。

applySpec()
{k: ((a, b, …, m) → v)} → ((a, b, …, m) → {k: v})
依照 spec object 建立新 object

{k: ((a, b, …, m) → v)}:新的 spec object,其 value 為 function

(a, b, …, m):餐數會套用到所有 value function

{k: v}:回傳新的 object

applecSpec() 配合 prop(),由於 Point-free,可讀性非常高,很明確看到新 property 與原 property

spec001

Conclusion


  • applySpec() 的 signature 看起來很嚇人,但只要靜下心看,其實也還好,且實際使用時,程式碼可讀性非常高

Reference


Ramda, map()
Ramda, applySpec()
Ramda, prop()