Я смотрю на функциональное программирование, где у меня есть следующий код:

const R   = require('ramda')
const original = {
  words: [
    { duration: '0.360000', name: 'Arthur', position: '0.660000' },
    { duration: '0.150000', name: 'the',    position: '1.020000' },
    { duration: '0.380000', name: 'rat',    position: '1.170000' },
    { duration: '0.770000', name: '.',      position: '1.550000' }
  ]
}

// 1. convert position and duration to int and multiply by 100
const makeInteger = a => parseFloat(a) * 100

const words = R.lensPath(['words'])
log('position', R.over(words, R.map(R.over(position, makeInteger)), original).words)

Возвращает :

position: [
    {
        duration: '0.360000',
        name: 'Arthur',
        position: 66
    },
    {
        duration: '0.150000',
        name: 'the',
        position: 102
    },
    {
        duration: '0.380000',
        name: 'rat',
        position: 117
    },
    {
        duration: '0.770000',
        name: '.',
        position: 155
    }
]

Как мне изменить и duration, и position в одной и той же функции, чтобы сделать их целыми числами?

После этого у меня будет эта функция, где я передаю индекс и обновляю все positions после этого пункта.

В основном мне нравится сдвигать смещение позиции в зависимости от объекта, где была изменена длительность?

const pos = R.over(words, R.map(R.over(position, makeInteger)), original)
const y = (i) => R.slice(i, Infinity, pos.words)
const foo = R.adjust(R.add(-2), 0, y(1))
log(foo)

И я получил

[
    NaN,
    {
        duration: '0.150000',
        name: 'the',
        position: 102
    },
    {
        duration: '0.380000',
        name: 'rat',
        position: 117
    },
    {
        duration: '0.770000',
        name: '.',
        position: 155
    }
]

Так что я застрял на том, как сместить позицию.

Любой совет высоко ценится.

0
khinester 11 Дек 2016 в 00:25

3 ответа

Лучший ответ

Я бы сделал что-то вроде этого, evolve и splitAt ваши друзья:

const {
  lensProp, lensIndex, splitAt, compose,
  curry, flatten, add, map, multiply,
  over, evolve
} = require('ramda')

const original = {
  words: [
    { duration: '0.360000', name: 'Arthur', position: '0.660000' },
    { duration: '0.150000', name: 'the',    position: '1.020000' },
    { duration: '0.380000', name: 'rat',    position: '1.170000' },
    { duration: '0.770000', name: '.',      position: '1.550000' }
  ]
}

const words = lensProp('words')
const snd = lensIndex(1)

const makeInt =
  compose(multiply(100), parseFloat)

const updateProps =
  evolve({ duration: makeInt, position: makeInt })

const offsetPos =
  offset => evolve({ duration: add(offset), position: add(offset) })

const wordsToInt =
  over(words, map(updateProps))

const offsetTail = curry(
  (offset, list) => over(snd, map(offsetPos(offset)))(list)
)

const applyOffset = curry(
  (indx, offset, list) => compose(
    flatten,
    offsetTail(offset),
    splitAt(indx)
  )(list)
)

const offsetWords = curry(
  (indx, offset, obj) =>
    over(words, applyOffset(indx, offset))(obj)
)

const flow =
  compose(offsetWords(2, -2), wordsToInt)

log(flow(original))
1
Ian Hofmann-Hicks 11 Дек 2016 в 01:26

Для вас первый вопрос, это легко.

const parsedList = words.map(word => {
    return {
        duration:parseInt(word.duration)*100,
        name,word.name,
        position: parseInt(word.position)*100
    }
})

.map - это новая функция ES6, которая перебирает массив, а затем возвращает новый массив. (Не изменяет массив, который он отображает, что является функциональным программированием 101)

Во-вторых, прости меня, если я ошибаюсь, но похоже, что .filter или .push сработают.

0
Flarp 10 Дек 2016 в 23:43

Другая версия, созданная по образцу @Ian Hoffman-Hicks, но с немного другим публичным API (flow принимает все три параметра) и несколько меньше промежуточных функций, выглядит так:

const wordsLens = lensProp('words') 

const makeInt = compose(multiply(100), parseFloat)

const offsetWords = curry((idx, offset, obj) => over(
  wordsLens, 
  lift(concat)(
    take(idx), 
    compose(
      map(evolve({position: add(offset)})), 
      drop(idx)
    )
  ), 
  obj
))

const flow = curry((idx, offset, obj) => offsetWords(
  idx, 
  offset, 
  over(
    wordsLens, 
    map(evolve({duration: makeInt, position: makeInt})), 
    obj
  )
))

flow(2, -2, original)

Вы можете увидеть это в действии на Ramda REPL .

Эта версия также использовала evolve, хотя и выбирается take и drop более splitAt. Это может или не может стоить учитывать для вас, но это по крайней мере показывает другой подход.

1
Community 23 Май 2017 в 11:45