如何將不規則 Object 轉成 Array ?

栏目: JavaScript · 发布时间: 5年前

内容简介:對於可有可無資料,後端 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'
};

至於 priceprice1price2 所對應的意義,定義在 lut object。

[ { title: 'General Price', price: 100 }, 
  { title: 'Shipping Price', price: 120 }, 
  { title: 'Duty-free price', price: 80 } ] 

我們希望結果為 array,其 element 為 object,且根據 lut 顯示對應的 titleprice

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 作法雖然能求得結果,但程式碼可讀性非常差。

如何將不規則 Object 轉成 Array ?

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 整合起來。

如何將不規則 Object 轉成 Array ?

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。

如何將不規則 Object 轉成 Array ?

Conclusion

  • Funtional 善於將問題最小化切割,然後各自擊破,最後再以 pipeline 加以整合,而不是如 imperative 一開始就思考如何整體解決問題
  • Point-free 可視自身能力與程式碼可讀性取捨,不需強求

以上所述就是小编给大家介绍的《如何將不規則 Object 轉成 Array ?》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

乔布斯离开了,马斯克来了

乔布斯离开了,马斯克来了

[日]竹内一正 / 干太阳 / 中信出版社 / 2015-11

在电动汽车的创新上,特斯拉抓住了一个群体的独特需求,外形很酷,不烧油,智能化控制。所有的颠覆式创新都不是敲锣打鼓来的,而是隐藏在一片噪声里,马斯克给我们带来的特斯拉虽然不尽完美,但他做产品的思维和执着于未来的勇气,值得学习。埃隆•马斯克创办公司也不是为了赚钱,而是为了拯救人类和地球,电动汽车、太阳能发电、宇宙火箭,不管是哪一项都足以令一个国家付出巨大的代价去研究开发,但埃隆•马斯克却一个人在做这些......一起来看看 《乔布斯离开了,马斯克来了》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

URL 编码/解码
URL 编码/解码

URL 编码/解码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具