如何將不規則 Object 轉成 Array ?
栏目: JavaScript · 发布时间: 6年前
内容简介:對於可有可無資料,後端 API 可能回傳 Object,其 Property 可能不存在,但對於前端而言,我們想要的是 Array 方便 HTML template 做VS Code 1.35.1Quokka 1.0.227
對於可有可無資料,後端 API 可能回傳 Object,其 Property 可能不存在,但對於前端而言,我們想要的是 Array 方便 HTML template 做 v-for ,本文由實際 API 回傳資料所改寫,接近實務上應用。
Version
VS Code 1.35.1
Quokka 1.0.227
Ramda 0.26.1
Imperative
let lut = {
price: 'General Price',
price1: 'Shipping Price',
price2: 'Duty-free price'
};
let data = {
title: 'FP in JavaScript',
price: 100,
prices: [
{
price1: 120,
price2: 80
}
]
};
// fn :: {a} -> {b} -> [{c}]
let fn = lut => obj => {
let result = [];
for(let x in obj) {
if (x === 'price') {
for(let z in lut) {
if (x === z) {
result.push({
title: lut[z],
price: obj[x]
});
}
}
}
if (x === 'prices') {
for(let y in obj.prices[0]) {
for(let z in lut) {
if (y === z) {
result.push({
title: lut[z],
price: obj.prices[0][y]
});
}
}
}
}
}
return result;
};
console.dir(fn(lut)(data));
第 7 行
let data = {
title: 'FP in JavaScript',
price: 100,
prices: [
{
price1: 120,
price2: 80
}
]
};
實際 data 為 object,不是 array,注意其 price 並不規則,主要 price 在第一層,其餘在 prices 下。
第 1 行
let lut = {
price: 'General Price',
price1: 'Shipping Price',
price2: 'Duty-free price'
};
至於 price 、 price1 與 price2 所對應的意義,定義在 lut object。
[ { title: 'General Price', price: 100 },
{ title: 'Shipping Price', price: 120 },
{ title: 'Duty-free price', price: 80 } ]
我們希望結果為 array,其 element 為 object,且根據 lut 顯示對應的 title 與 price 。
18 行
// fn :: {a} -> {b} -> [{c}]
let fn = lut => obj => {
let result = [];
for(let x in obj) {
if (x === 'price') {
for(let z in lut) {
if (x === z) {
result.push({
title: lut[z],
price: obj[x]
});
}
}
}
if (x === 'prices') {
for(let y in obj.prices[0]) {
for(let z in lut) {
if (y === z) {
result.push({
title: lut[z],
price: obj.prices[0][y]
});
}
}
}
}
}
return result;
};
由於結果為 array,imperative 會先建立 result array,使用 for in loop 讀取 property,再加上各種 if 判斷,建立 object 然後 push 進 result array。
我們發現 imperative 作法雖然能求得結果,但程式碼可讀性非常差。
Functional
import { pipe, keys, filter, __, has, map } from 'ramda';
let lut = {
price: 'General Price',
price1: 'Shipping Price',
price2: 'Duty-free price'
};
let data = {
title: 'FP in JavaScript',
price: 100,
prices: [
{
price1: 120,
price2: 80
}
]
};
// pickAllPrice :: {a} -> {b}
let pickAllPrice = obj => ({
...obj,
...obj.prices[0]
});
// objToArr :: {a} -> {b} -> [{c}]
let objToArr = lut => obj => pipe(
keys,
filter(x => has(x, obj)),
map(x => ({ title: lut[x], price: obj[x]}))
)(lut);
// fn :: {a} -> {b} -> [{c}]
let fn = lut => obj => pipe(
pickAllPrice,
objToArr(lut),
)(obj);
console.dir(fn(lut)(data));
以 Functional 角度思考:
price
20 行
// pickAllPrice :: {a} -> {b}
let pickAllPrice = obj => ({
...obj,
...obj.prices[0]
});
pickAllPrice() 將所有 prices 下的 property 全部整理到 object 第一層 property
27 行
// objToArr :: {a} -> {b} -> [{c}]
let objToArr = lut => obj => pipe(
keys,
filter(x => has(x, obj)),
map(x => ({ title: lut[x], price: obj[x]}))
)(lut);
要將 object 轉成 array, keys() 是關鍵 function,它將 object 中所有的 key 轉成 array。
但 prices 下的 property 個數並不確定,可能只有 price1 而沒有 price2 ,因此搭配 filter() 與 has() ,只過濾出 prices 下實際有的 property。
最後使用 map() 整理出我們要的格式。
33 行
// fn :: {a} -> {b} -> [{c}]
let fn = lut => obj => pipe(
pickAllPrice,
objToArr(lut),
)(obj);
將問題各個擊破後,最後由 fn() 將所有 function 整合起來。
Point-free
import { pipe, keys, filter, __, has, map, applySpec, prop } from 'ramda';
let lut = {
price: 'General Price',
price1: 'Shipping Price',
price2: 'Duty-free price'
};
let data = {
title: 'FP in JavaScript',
price: 100,
prices: [
{
price1: 120,
price2: 80
}
]
};
// pickAllPrice :: {a} -> {b}
let pickAllPrice = obj => ({
...obj,
...obj.prices[0]
});
// objToArr :: {a} -> {b} -> [{c}]
let objToArr = lut => obj => pipe(
keys,
filter(has(__, obj)),
map(applySpec({
title: prop(__, lut),
price: prop(__, obj)
}))
)(lut);
// fn :: {a} -> {b} -> [{c}]
let fn = lut => obj => pipe(
pickAllPrice,
objToArr(lut),
)(obj);
console.dir(fn(lut)(data));
filter() 與 map() 的 callback 可再進一步 point-free。
29 行
filter(has(__, obj)),
別忘了 has() 的 currying 特性,可以 has() 直接產生 filter() 所需的 callback。
30 行
map(applySpec({
title: prop(__, lut),
price: prop(__, obj)
}))
map() 的 callback 也能再使用 applySpec() 使其 point-free。
Conclusion
- Funtional 善於將問題最小化切割,然後各自擊破,最後再以 pipeline 加以整合,而不是如 imperative 一開始就思考如何整體解決問題
- Point-free 可視自身能力與程式碼可讀性取捨,不需強求
以上所述就是小编给大家介绍的《如何將不規則 Object 轉成 Array ?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Google御用網頁語言Node.js
郭家寶 / 佳魁資訊 / 2013-4-26 / NT 490
這是一本 Node.js 的入門教學,寫給想要學習 Node.js,但沒有任何系統的經驗的開發者。如果你聽說過 Node.js,並被它許多神奇的特性吸引,本書就是為你準備的。 透過閱讀本書,你可以對 Node.js 有全面的認識,學會如何用 Node.js 程式設計,了解事件驅動、非同步式 I/O 的程式設計模式,同時還可以了解一些使用JavaScript 進行函數式程式設計的方法。 ......一起来看看 《Google御用網頁語言Node.js》 这本书的介绍吧!