Javascript 函数式编程修改数组中的两个项
我正在研究函数式编程,目前为止我有以下代码:Javascript 函数式编程修改数组中的两个项,javascript,ramda.js,Javascript,Ramda.js,我正在研究函数式编程,目前为止我有以下代码: 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
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
}
]
如何在同一函数中修改持续时间
和位置
,使其成为整数
接下来,我将使用这个函数传递索引并更新该点之后的所有位置
基本上,我喜欢根据修改“持续时间”的对象来移动“位置”偏移量
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
}
]
所以我被困在如何抵消这个位置上
非常感谢您的建议。对于您的第一个问题,这很简单
const parsedList = words.map(word => {
return {
duration:parseInt(word.duration)*100,
name,word.name,
position: parseInt(word.position)*100
}
})
.map是一个新的ES6函数,它在数组上循环,然后返回一个新数组。(不改变其映射的数组,这是函数式编程101)
对于你的第二个问题,如果我错了,请原谅我,但听起来.filter或.push都可以用。对于你的第一个问题,这很简单
const parsedList = words.map(word => {
return {
duration:parseInt(word.duration)*100,
name,word.name,
position: parseInt(word.position)*100
}
})
.map是一个新的ES6函数,它在数组上循环,然后返回一个新数组。(不改变其映射的数组,这是函数式编程101)
对于你的第二个问题,如果我错了,请原谅我,但听起来.filter或.push都可以用。我会这样做,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))
我会这样做,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))
另一个版本是以中的版本为模型的,但具有稍微不同的公共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)
您可以在上看到这一点
这个版本也被使用了,尽管它选择了并多次使用。这可能值得您考虑,也可能不值得您考虑,但它至少显示了一种不同的方法。另一个版本,以来自的版本为模型,但具有稍微不同的公共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)
您可以在上看到这一点
这个版本也被使用了,尽管它选择了并多次使用。这对你来说可能值得考虑,也可能不值得考虑,但它至少显示了一种不同的方法。不错,这很完美@scott sauyet的答案非常好。他使用lift
和concat
(以及任何n元>1函数)是拉姆达在处理列表时的一种超级强大的模式。不错,这是完美的@scott sauyet的答案非常好。他使用lift
和concat
(以及任何n元>1函数)是拉姆达在处理列表时的一种超级强大的模式。感谢您的回复,非常好,学到了更多。感谢您的回复,非常好,学到了更多。