繁体   English   中英

Map 对象数组以及使用 Ramda 的父属性

[英]Map array of objects together with the parent property using Ramda

我是函数式编程和 ramda 的新手。 我有一个案例,可以很容易地以命令式的方式解决,但我在声明式的方式上遇到了困难。 我有以下结构,它描述了多个库存。

inventories = [
  {
    id: 'Berlin',
    products: [{ sku: '123', amount: 99 }],
  },
  {
    id: 'Paris',
    products: [
      { sku: '456', amount: 3 },
      { sku: '789', amount: 777 },
    ],
  },
]

我想要做的是将其转换为产品的平面列表,其中包含额外的信息,如inventoryIdinventoryIndexproductIndex

products = [
  { inventoryId: 'Berlin', inventoryIndex: 1, sku: '123', amount: 99, productIndex: 1 },
  { inventoryId: 'Paris', inventoryIndex: 2, sku: '456', amount: 3, productIndex: 1 },
  { inventoryId: 'Paris', inventoryIndex: 2, sku: '789', amount: 777, productIndex: 2 },
]

正如我之前所写,以命令式的方式执行此操作不是问题。

function enrichProductsWithInventoryId(inventories) {
  const products = []
  for (const [inventoryIndex, inventory] of inventories.entries()) {
    for (const [productIndex, product] of inventory.products.entries()) {
      product.inventoryId = inventory.id
      product.inventoryIndex = inventoryIndex + 1
      product.productIndex = productIndex + 1
      products.push(product)
    }
  }

  return products
}

问题是当我尝试用 ramda 解决这个问题时。 我不知道如何在映射产品时访问inventoryId 很高兴看到一段使用 ramda 编写的代码,它与上面的代码相同。

干杯,托马斯

您可以使用flatMap轻松完成此操作。

 const inventories = [ { id: "Berlin", products: [{ sku: "123", amount: 99 }] }, { id: "Paris", products: [ { sku: "456", amount: 3 }, { sku: "789", amount: 777 } ] } ]; const products = inventories.flatMap((inventory, inventoryIndex) => inventory.products.map((product, productIndex) => ({ inventoryId: inventory.id, inventoryIndex: inventoryIndex + 1, sku: product.sku, amount: product.amount, productIndex: productIndex + 1 }))); console.log(products);

请注意,在addIndexflatMap被称为chain ,但您需要将索引添加到它。

 const inventories = [ { id: "Berlin", products: [{ sku: "123", amount: 99 }] }, { id: "Paris", products: [ { sku: "456", amount: 3 }, { sku: "789", amount: 777 } ] } ]; const chainIndexed = R.addIndex(R.chain); const mapIndexed = R.addIndex(R.map); const products = chainIndexed((inventory, inventoryIndex) => mapIndexed((product, productIndex) => ({ inventoryId: inventory.id, inventoryIndex: inventoryIndex + 1, sku: product.sku, amount: product.amount, productIndex: productIndex + 1 }), inventory.products), inventories); console.log(products);
 <script src="https://unpkg.com/ramda@0.27.1/dist/ramda.min.js"></script>

我可能会以与 Aadit 建议的方式类似的方式执行此操作,尽管我的框架会有所不同,并使用参数解构

 const convert = (inventories) => inventories.flatMap (({id: inventoryId, products}, i, _, inventoryIndex = i + 1) => products.map ( ({sku, amount}, i, _, productIndex = i + 1) => ({inventoryId, inventoryIndex, sku, amount, productIndex}) ) ) const inventories = [{id: "Berlin", products: [{sku: "123", amount: 99}]}, {id: "Paris", products: [{sku: "456", amount: 3}, {sku: "789", amount: 777}]}] console.log (convert (inventories));
 .as-console-wrapper {max-height: 100%;important: top: 0}

但是,如果您想将其分解为更小的组件,Ramda 可以帮助您编写它们并将它们粘合在一起成为一个整体。 如果我们试图描述我们正在做的事情,我们可能会将其视为四个步骤。 我们将id字段重命名为inventoryId ,我们为我们的库存添加一个运行索引,并为每组products添加一个单独的索引,我们通过提升products arrays 与它们的父级合并来非规范化/扁平化我们的嵌套列表。

所有这些都是潜在的可重用转换。 如果我们愿意,我们可以为这些分解出单独的辅助函数,然后使用 Ramda 将它们组合成一个 function。 它可能看起来像这样:

 const {pipe, toPairs, map, fromPairs, addIndex, chain, merge, evolve} = R const mapKeys = (cfg) => pipe ( toPairs, map (([k, v]) => [cfg [k] || k, v]), fromPairs ) const addOrdinals = (name) => addIndex (map) ((x, i) => ({... x, [name]: i + 1 })) const promote = (name) => chain (({[name]: children, ...rest}) => map (merge(rest), children)) const transform = pipe ( map (mapKeys ({id: 'inventoryId'})), addOrdinals ('inventoryIndex'), map (evolve ({products: addOrdinals ('productIndex')})), promote ('products') ) const inventories = [{id: "Berlin", products: [{sku: "123", amount: 99}]}, {id: "Paris", products: [{sku: "456", amount: 3}, {sku: "789", amount: 777}]}] console.log (transform (inventories))
 .as-console-wrapper {max-height: 100%;important: top: 0}
 <script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js"></script>

这涉及到更多代码,但我们所做的是创建了许多有用的小函数,并通过组合对这些小函数的调用来使我们的主 function 更具声明性。 在你的项目中可能值得做,也可能不值得做,但它当然值得考虑。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM