简体   繁体   中英

How to map one to many?

Simplified question is that I have array ['a', 'b', 3, 'c'] and I want to change 3 with null, null, null like this ['a', 'b', null, null, null, 'c'] how can I do it with Ramda?

this is my full code

const R = require('ramda')

const getBoardStateFromBoardString = R.pipe(
    R.split(''),
    R.map(
        R.cond([
            [
                R.test(/[bfmterk]/),
                R.assoc('piece', R.__, { color: 'b' })
            ],
            [
                R.test(/[BFMTERK]/),
                R.assoc('piece', R.__, { color: 'w' })
            ],
            [
                R.test(/\d/),
                R.pipe(
                    R.assoc('padding', R.__, {}),
                    R.evolve({ padding: parseInt })
                )
            ],
            [
                R.equals('/'),
                R.always({ padding: 8 })
            ]
        ])
    ),
)

console.log(getBoardStateFromBoardString('rmtektmr/8/bbbbbbbb/8/8/BBBBBBBB/8/RMTKETMR'))

result

[
  { color: 'b', piece: 'r' },
  { color: 'b', piece: 'm' },
  { color: 'b', piece: 't' },
  { color: 'b', piece: 'e' },
  { color: 'b', piece: 'k' },
  { color: 'b', piece: 't' },
  { color: 'b', piece: 'm' },
  { color: 'b', piece: 'r' },
  { padding: 8 },
  { padding: 8 },
  { padding: 8 },
  { color: 'b', piece: 'b' },
  ...
]

What I want is to map single { padding: 8 } to 8 null like this...

[
  { color: 'b', piece: 'r' },
  { color: 'b', piece: 'm' },
  { color: 'b', piece: 't' },
  { color: 'b', piece: 'e' },
  { color: 'b', piece: 'k' },
  { color: 'b', piece: 't' },
  { color: 'b', piece: 'm' },
  { color: 'b', piece: 'r' },

  null,
  null,
  null,
  null,
  null,
  null,
  null,
  null,

  null,
  null,
  null,
  null,
  null,
  null,
  null,
  null,

  null,
  null,
  null,
  null,
  null,
  null,
  null,
  null,

  { color: 'b', piece: 'b' },
  ...
]

So I wrote code that I want without Ramda like this...

function getBoardStateFromBoardString(boardString) {
    const boardState = Array(128)
    let i = 0
    for (const symbol of boardString) {
        if (/[bfmterk]/.test(symbol)) {
            boardState[i] = {
                piece: symbol,
                color: 'b'
            }
            i++
        } else if (/[BFMTERK]/.test(symbol)) {
            boardState[i] = {
                piece: symbol,
                color: 'w'
            }
            i++
        } else if (/\d/.test(symbol)) {
            i += parseInt(symbol, 10)
        } else if (symbol === '/') {
            i += 8
        }
    }

    return boardState
}

But I have no idea how to do with Ramda (with point-free style if possible)?

You can use R.chain to iterate the array items, and flatten the results. If an item is a number, use repeat to create an array of null values.

 const { chain, when, is, repeat } = R const fn = chain(when(is(Number), repeat(null))) const arr = ['a', 'b', 3, 'c'] const result = fn(arr) console.log(result)
 <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>

In your case, you can use R.cond with R.chain, and replace the creation of a padding object with repeated null :

 const { pipe, split, chain, cond, test, applySpec, identity, always, equals, repeat } = R const getBoardStateFromBoardString = pipe( split(''), chain( cond([ [ test(/[bfmterk]/), applySpec({ piece: identity, color: always('b') }) ], [ test(/[BFMTERK]/), applySpec({ piece: identity, color: always('w') }) ], [ test(/\\d/), repeat(null) ], [ equals('/'), always(repeat(null, 8)) ] ]) ), ) const result = getBoardStateFromBoardString('rmtektmr/8/bbbbbbbb/8/8/BBBBBBBB/8/RMTKETMR') console.log(result)
 <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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