我有的问题是我正在使用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:“正在打包订单”
控制台日志输入2:“订单已交付”
控制台日志输入3:“新制作”


谢谢

最佳答案

丑陋的解决方案

在没有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对象强加给您,而您只需要处理它,或者它是否属于您自己的构造。下面,我将讨论清理它的方法,但是首先,我们可能想做一件事来处理至少一个可能的失败案例:

处理丢失的statusType

如果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


清理配置对象

这里的复杂性在于配置对象内。我们用与neworder不同的结构来处理delivery情况。并且我们将消息嵌套在看起来不必要的额外级别上(为什么不将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,
                orderStatus: pack
              },
              Time: '2019-08-12T08:55:28Z',
              statusType: 'order',
            }


我们声明statusTypeorder,然后将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))





经验教训

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

关于javascript - Ramda JS如何使用2个json文件映射特定值,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59898323/

10-11 07:06