Ramda JS 如何使用 2 json 文件映射特定值

Ramda JS how to map a specific value using 2 json file

我遇到的问题是我使用 2 个 json 文件来映射事件的状态,但我不确定如何在 ramda

中做到这一点
const input1 = {
              data: {
                memberId: 12345,
                orderStatus: pack
              },
              Time: '2019-08-12T08:55:28Z',
              statusType: 'order',
            }

const input2 = {
              data: {
                memberId: 12345,
                deliveryStatus: dispatch
              },
              Time: '2019-08-12T08:55:28Z',
              statusType: 'delivery',
            }

const input3 = {
              data: {
                memberId: 12345,
              },
              Time: '2019-08-12T08:55:28Z',
              statusType: 'new',
            }

const status = {
  'order': {
      orderStatus: {
        pack: 'order is being pack',
        cancelled: 'cancel order'
    },
  },
  'delivery': {
      deliveryStatus: {
        pending: 'pending',
        dispatch: 'order has been delivered'
    },
  },
  'new': 'newly made'
}
  1. 控制台日志输入1:"order is being pack"
  2. 控制台日志输入2:"order has been delivered"
  3. 控制台日志输入3:"newly made"

谢谢

一个丑陋的解决方案

我们可以在没有 Ramda 的情况下以一种有点复杂的方式做到这一点:

const statusHandler = (statuses) => {
  const handlers = Object .fromEntries (Object .entries (status)
    .map (([name, val]) => typeof val == 'string'
      ? [name, () => val]
      : [name, ({data}) => val [name + 'Status'] [data [name + 'Status']]]
    ))
 
  return (item) => handlers [item .statusType] (item)
}
 
const status = {
  order: {
    orderStatus: {
      pack: 'order is being pack', 
      cancelled: 'cancel order'
    }
  }, 
  delivery: {
    deliveryStatus: {
      pending: 'pending', 
      dispatch: 'order has been delivered'
    }
  }, 
  new: 'newly made'
}
 
const getStatus = statusHandler (status)
 
const input1 = {data: {memberId: 12345, orderStatus: 'pack'}, Time: '2019-08-12T08:55:28Z', statusType: 'order'}
const input2 = {data: {memberId: 12345, deliveryStatus: 'dispatch'}, Time: '2019-08-12T08:55:28Z', statusType: 'delivery'}
const input3 = {data: {memberId: 12345}, Time: '2019-08-12T08:55:28Z', statusType: 'new'}
 
console .log (getStatus (input1))
console .log (getStatus (input2))
console .log (getStatus (input3))

我看不出 Ramda 会在这里提供多少简化,也许用 fromPairstoPairs 代替 Object .fromEntriesObject .entries 来稍微缩短一些东西,或者使用 Ramda 的 map 更好,它适用于对象,也许使用 pipe 进行一些额外的简化,但它不会解决这个主要问题,我们搜索的键必须构造并且我们的配置对象 status 包含两个不同的结构,而不是对所有结构都是一致的。

我不知道 status 对象是强加给你的,你只需要处理它,还是它是你自己构造的。下面我将讨论清理它的方法,但首先,我们可能想要做一件事来处理至少一个可能的失败案例:

正在处理丢失的 statusTypes

如果 statusType 不在我们的类型列表中,那么这将失败。也许您的数据足够一致,这种情况永远不会发生,但我经常看到假设不可能的数据情况导致应用程序崩溃。所以这个扩展可能会让它更干净。

const statusHandler = (statuses) => {
  const handlers = Object .fromEntries (Object .entries (status)
    .map (([name, val]) => typeof val == 'string'
      ? [name, () => val]
      : [name, ({data}) => val [name + 'Status'] [data [name + 'Status']]]
    ))
  const defaultHandler = () => 'unknown status type'  // New line

  return (item) => (handlers [item .statusType] || defaultHandler) (item)  // Updated
}

这样我们就可以处理这样的情况:

const input4 = {data: {memberId: 12345}, Time: '2019-08-12T08:55:28Z', statusType: 'foobar'}

getStatus (input4) //=> unknown status type

正在清理配置对象

这里的复杂性在于配置对象。我们使用与 orderdelivery 不同的结构处理 new 案例。我们将消息嵌套在看起来不必要的额外级别(为什么不将 orderStatusdeliveryStatus 的内容移到它们的父级?)正如我所说,这可能是我们现有的结构无法控制,上面的答案可能是我们能做的最好的。但是如果我们可以控制这个结构,那么这会更明确,并且会导致更清晰的代码:

const statusHandler = (statuses) => (item) => {
  const type = statuses [item .statusType] || statuses ['*']
  return type [item .data [item .statusType + 'Status'] || '*']
}

const status = {
  order: {
    pack: 'order is being pack', 
    cancelled: 'cancel order',
    '*': 'unknown order status'
  }, 
  delivery: {
    pending: 'pending', 
    dispatch: 'order has been delivered',
    '*': 'unknown delivery status'
  }, 
  new: {
    '*': 'newly made'   
  },
  '*': {
    '*': 'unknown status type'
  }
}

这也解释了另一个潜在的失败:

const input5 = {data: {memberId: 12345, status: 'collection'}, Time: '2019-08-12T08:55:28Z', statusType: 'order'}

getStatus (input5) //=> unknown order status

由于添加了配置对象,我们实际上可能使行数更长了。但总的来说,简单得多。我们的配置对象完全描述了我们为状态和阶段的任意组合获得的输出类型。我们的代码只是将其转换为数据项中的函数。

您可以在这段代码中看到它的实际效果:

const statusHandler = (statuses) => (item) => {
  const type = statuses [item .statusType] || statuses ['*']
  return type [item .data [item .statusType + 'Status'] || '*']
}

const status = {
  order: {
    pack: 'order is being pack', 
    cancelled: 'cancel order',
    '*': 'unknown order status'
  }, 
  delivery: {
    pending: 'pending', 
    dispatch: 'order has been delivered',
    '*': 'unknown delivery status'
  }, 
  new: {
    '*': 'newly made'   
  },
  '*': {
    '*': 'unknown status type'
  }
}
 
const getStatus = statusHandler (status)
 
const input1 = {data: {memberId: 12345, orderStatus: 'pack'}, Time: '2019-08-12T08:55:28Z', statusType: 'order'}
const input2 = {data: {memberId: 12345, deliveryStatus: 'dispatch'}, Time: '2019-08-12T08:55:28Z', statusType: 'delivery'}
const input3 = {data: {memberId: 12345}, Time: '2019-08-12T08:55:28Z', statusType: 'new'}
const input4 = {data: {memberId: 12345}, Time: '2019-08-12T08:55:28Z', statusType: 'foobar'}
const input5 = {data: {memberId: 12345, status: 'collection'}, Time: '2019-08-12T08:55:28Z', statusType: 'order'}
 
console .log (getStatus (input1))
console .log (getStatus (input2))
console .log (getStatus (input3))
console .log (getStatus (input4))
console .log (getStatus (input5))

清理项目中的重复项

最后,即使我们可以控制这个配置对象,我们也可能无法控制输入数据对象。但是如果我们这样做,那里就会有一些冗余,这不仅是不必要的,而且还会导致我们在函数中进行烦人的字符串操作:

const input1 = {
              data: {
                memberId: 12345,
                <b>order</b>Status: pack
              },
              Time: '2019-08-12T08:55:28Z',
              statusType: '<b>order</b>',
            }

我们声明orderstatusType,然后将orderStatus设置为pack。将 orderStatus 替换为简单的 status 有一个明确的论据。因此,如果我们也能控制这些数据,我们将拥有更一致的数据,我们的功能也可以更简单。

我们可以在这段代码中看到这种可能性:

const statusHandler = (statuses) => (item) => {
  const type = statuses [item .statusType] || statuses ['*']
  return type [item .data .status || '*'] || type ['*']
}

const status = {
  order: {
    pack: 'order is being pack', 
    cancelled: 'cancel order',
    '*': 'unknown order status'
  }, 
  delivery: {
    pending: 'pending', 
    dispatch: 'order has been delivered',
    '*': 'unknown delivery status'
  }, 
  new: {
    '*': 'newly made'   
  },
  '*': {
    '*': 'unknown status type'
  }
}
 
const getStatus = statusHandler (status)
 
const input1 = {data: {memberId: 12345, status: 'pack'}, Time: '2019-08-12T08:55:28Z', statusType: 'order'}
const input2 = {data: {memberId: 12345, status: 'dispatch'}, Time: '2019-08-12T08:55:28Z', statusType: 'delivery'}
const input3 = {data: {memberId: 12345}, Time: '2019-08-12T08:55:28Z', statusType: 'new'}
const input4 = {data: {memberId: 12345}, Time: '2019-08-12T08:55:28Z', statusType: 'foobar'}
const input5 = {data: {memberId: 12345, status: 'collection'}, Time: '2019-08-12T08:55:28Z', statusType: 'order'}
 
console .log (getStatus (input1))
console .log (getStatus (input2))
console .log (getStatus (input3))
console .log (getStatus (input4))
console .log (getStatus (input5))

课程

我们可以通过使我们的数据结构更简单和更一致来简化我们的代码。这使我们能够使我们的整个系统更具声明性。请注意,最终函数不仅更简单,而且更有可能跨应用程序的不同部分或不同应用程序重用。