将多维数组上的Array.reduce转换为对象数组

Jac*_*art 2 javascript arrays poker functional-programming

在我的扑克应用程序中,我有一系列的手,每一手都是随机选择的卡片对象的数组,有价值和适合:

[ [ { value: 5, suit: 's' },
    { value: 4, suit: 's' },
    { value: 6, suit: 'c' },
    { value: 11, suit: 'd' },
    { value: 12, suit: 'c' } ],
  [ { value: 9, suit: 'd' },
    { value: 12, suit: 'h' },
    { value: 8, suit: 'c' },
    { value: 12, suit: 's' },
    { value: 2, suit: 's' } ],
  [ { value: 4, suit: 'h' },
    { value: 6, suit: 's' },
    { value: 10, suit: 'c' },
    { value: 3, suit: 'd' },
    { value: 7, suit: 'd' } ] ]
Run Code Online (Sandbox Code Playgroud)

为了准备评估的手,我想使用Array.reduce返回一个手对象数组.所以输出将是:

[ 
  { 
    values: [5, 4, 6, 11, 12],
    suits: ['s', 's', 'c', 'd', 'c'] 
  },      
  { 
    values: [9, 12, 8, 12, 2], 
    suits: ['d', 'h', 'c', 's', 's'] 
  },
  { 
    values: [4, 6, 10, 3, 7],
    suits: ['h', 's', 'c', 'd', 'd'] 
  } 
]
Run Code Online (Sandbox Code Playgroud)

我尝试用嵌套的forEach实现这个,但它失败了,我不知道为什么.我有两个console.log,其输出符合预期,但最后的手与输入相同.

let temp = []
hands.forEach((el) => {
  temp = el
  el = {}
  el.values = []
  el.suits = []
  console.log(el) //expected output
  temp.forEach((obj) => {
    el.values.push(obj.value)
    el.suits.push(obj.suit)
    console.log(el) //expected output
  })
})
console.log(hands) //same as original
Run Code Online (Sandbox Code Playgroud)

Tha*_*you 8

你必须考虑输入数据(DATA)和输出(DATA')的形状

在此输入图像描述

1:1之间的关系HANDHAND'意义我们将Array.prototype.map用于一次转换.另一方面,与我们将用于该转换的meaing CARDN:1的关系HAND'Array.prototype.reduce

在此输入图像描述

所以在我们工作的时候记住,我们将做一张地图和一个减少

const data = 
  [ [ { value: 5, suit: 's' },
      { value: 4, suit: 's' },
      { value: 6, suit: 'c' },
      { value: 11, suit: 'd' },
      { value: 12, suit: 'c' } ],
    [ { value: 9, suit: 'd' },
      { value: 12, suit: 'h' },
      { value: 8, suit: 'c' },
      { value: 12, suit: 's' },
      { value: 2, suit: 's' } ],
    [ { value: 4, suit: 'h' },
      { value: 6, suit: 's' },
      { value: 10, suit: 'c' },
      { value: 3, suit: 'd' },
      { value: 7, suit: 'd' } ] ]

let output = 
  data.map(cards =>
    cards.reduce(({values, suits}, {value, suit}) => ({
      values: [...values, value],
      suits: [...suits, suit]
    }), {values: [], suits: []}))

console.log(output)
Run Code Online (Sandbox Code Playgroud)

现在当然看起来有点密集,所以如果我们能够稍微降低复杂性,那就太好了.通过制作一些curried适配器map,reduce我们可以表达一个非常好地执行转换的功能

const data = 
  [ [ { value: 5, suit: 's' },
      { value: 4, suit: 's' },
      { value: 6, suit: 'c' },
      { value: 11, suit: 'd' },
      { value: 12, suit: 'c' } ],
    [ { value: 9, suit: 'd' },
      { value: 12, suit: 'h' },
      { value: 8, suit: 'c' },
      { value: 12, suit: 's' },
      { value: 2, suit: 's' } ],
    [ { value: 4, suit: 'h' },
      { value: 6, suit: 's' },
      { value: 10, suit: 'c' },
      { value: 3, suit: 'd' },
      { value: 7, suit: 'd' } ] ]


const map = f => xs => xs.map(f)

const reduce = f => y => xs => xs.reduce(f, y)

const handAppendCard = ({values, suits}, {value, suit}) => ({
  values: [...values, value],
  suits: [...suits, suit]
})

const makeHands =
  map (reduce (handAppendCard) ({values:[], suits:[]}))

let output = makeHands (data)

console.log(output)
Run Code Online (Sandbox Code Playgroud)

这只是解决问题的一种方法.我希望你能从中学到一些东西^ _ ^