使用 Ramda 减少 "position" 属性
Decrease "position" property with Ramda
有了这个对象:
const state = {
a: {position: 1},
b: {position: 2},
c: {position: 3},
d: {position: 4},
e: {position: 5},
}
我想删除 b
对象,然后将具有更高位置的对象的 position
减 1(所以只是为了 c
、d
和 e
)。结果状态应该是:
{
a: {position: 1},
c: {position: 2},
d: {position: 3},
e: {position: 4},
}
在玩了 Ramda 之后,我得到了这样的结果:
const removeElement = (state, elementId) => {
const newState = dissoc('b', state)
return pipe(
filter((currentDoc) => currentDoc.position > state[elementId].position),
clone,
forEachObjIndexed((value, key) => (value.position-=1), __),
merge(newState)
)(newState)
}
removeElement(state, 'b')
它可以工作,但我对它不是很满意,因为我觉得它有点冗长。你觉得有更好的写法吗?
只需过滤和更新。然后删除。
const state = { b: { position: 2 }, c: { position: 3 }, d: { position: 4 }, e: { position: 5 }, a: { position: 1 } };
Object
.values(state)
.filter(o => o.position > state.b.position)
.forEach(o => o.position--);
delete state.b;
console.log(state);
使用 lenses 的 ramda 解决方案:
const { pipe, dissoc, lensProp, map, over, dec, gt, view, when, flip, prop } = R
const pLens = lensProp('position');
const removeElement = (state, elementId) => pipe(
dissoc(elementId),
map(when(
pipe(
view(pLens),
flip(gt)(view(pLens, prop(elementId, state))
)),
over(pLens, dec)
))
)(state)
const state = {"a":{"position":1},"b":{"position":2},"c":{"position":3},"d":{"position":4},"e":{"position":5}}
const result = removeElement(state, 'b')
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
我会把事情分开一点:
首先是一个函数,该函数 returns 一个检查 {position}
对象是否具有 position
属性 小于给定数字的函数:
const positionLowerThan = (num) => propSatisfies(lt(num), 'position');
其次,一个函数将接受一个 {position}
对象并简单地减少它的 position
属性:
const decreasePosition = over(lensProp('position'), dec);
把所有东西放在一起:
const {propSatisfies, over, lensProp, dec, pipe, omit, map, when, lt} = R;
const positionLowerThan = (num) => propSatisfies(lt(num), 'position');
const decreasePosition = over(lensProp('position'), dec);
const execute = (key, obj) =>
pipe(omit([key]), map(when(positionLowerThan(obj[key].position), decreasePosition)))
(obj);
console.log(
execute('b', {
a: {position: 1},
b: {position: 2},
c: {position: 3},
d: {position: 4},
e: {position: 5},
})
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
我可能会这样做:
const {dissoc, map} = R
const reshape = (state, key, pos = state[key].position) => dissoc(key, map(
({position}) => position > pos ? {position: position - 1} : {position},
state
))
const state = { a: { position: 1 }, b: { position: 2 }, c: { position: 3 }, d: { position: 4 }, e: { position: 5 }, };
console.log(reshape(state, 'b'))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
请注意,Nina 和 customcommander 之间关于 remove 的讨论与此处相关。此版本不会更改您的原始版本。 Ramda 强调永远不要这样做。
如果您的状态值不仅仅是 {position: ?}
,那么这个版本应该可以解决问题:
const reshape = (state, key, pos = state[key].position) => dissoc(key, map(
({position, ...rest}) => position > pos
? {position: position - 1, ...rest}
: {position, ...rest},
state
))
或者,正如 Emi 指出的那样,这个版本的性能可能更高:
const reshape = (state, key, pos = state[key].position) => dissoc(key, map(
(obj) => obj.position > pos ? {...obj, position: obj.position - 1} : obj,
state
))
有了这个对象:
const state = {
a: {position: 1},
b: {position: 2},
c: {position: 3},
d: {position: 4},
e: {position: 5},
}
我想删除 b
对象,然后将具有更高位置的对象的 position
减 1(所以只是为了 c
、d
和 e
)。结果状态应该是:
{
a: {position: 1},
c: {position: 2},
d: {position: 3},
e: {position: 4},
}
在玩了 Ramda 之后,我得到了这样的结果:
const removeElement = (state, elementId) => {
const newState = dissoc('b', state)
return pipe(
filter((currentDoc) => currentDoc.position > state[elementId].position),
clone,
forEachObjIndexed((value, key) => (value.position-=1), __),
merge(newState)
)(newState)
}
removeElement(state, 'b')
它可以工作,但我对它不是很满意,因为我觉得它有点冗长。你觉得有更好的写法吗?
只需过滤和更新。然后删除。
const state = { b: { position: 2 }, c: { position: 3 }, d: { position: 4 }, e: { position: 5 }, a: { position: 1 } };
Object
.values(state)
.filter(o => o.position > state.b.position)
.forEach(o => o.position--);
delete state.b;
console.log(state);
使用 lenses 的 ramda 解决方案:
const { pipe, dissoc, lensProp, map, over, dec, gt, view, when, flip, prop } = R
const pLens = lensProp('position');
const removeElement = (state, elementId) => pipe(
dissoc(elementId),
map(when(
pipe(
view(pLens),
flip(gt)(view(pLens, prop(elementId, state))
)),
over(pLens, dec)
))
)(state)
const state = {"a":{"position":1},"b":{"position":2},"c":{"position":3},"d":{"position":4},"e":{"position":5}}
const result = removeElement(state, 'b')
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
我会把事情分开一点:
首先是一个函数,该函数 returns 一个检查 {position}
对象是否具有 position
属性 小于给定数字的函数:
const positionLowerThan = (num) => propSatisfies(lt(num), 'position');
其次,一个函数将接受一个 {position}
对象并简单地减少它的 position
属性:
const decreasePosition = over(lensProp('position'), dec);
把所有东西放在一起:
const {propSatisfies, over, lensProp, dec, pipe, omit, map, when, lt} = R;
const positionLowerThan = (num) => propSatisfies(lt(num), 'position');
const decreasePosition = over(lensProp('position'), dec);
const execute = (key, obj) =>
pipe(omit([key]), map(when(positionLowerThan(obj[key].position), decreasePosition)))
(obj);
console.log(
execute('b', {
a: {position: 1},
b: {position: 2},
c: {position: 3},
d: {position: 4},
e: {position: 5},
})
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
我可能会这样做:
const {dissoc, map} = R
const reshape = (state, key, pos = state[key].position) => dissoc(key, map(
({position}) => position > pos ? {position: position - 1} : {position},
state
))
const state = { a: { position: 1 }, b: { position: 2 }, c: { position: 3 }, d: { position: 4 }, e: { position: 5 }, };
console.log(reshape(state, 'b'))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
请注意,Nina 和 customcommander 之间关于 remove 的讨论与此处相关。此版本不会更改您的原始版本。 Ramda 强调永远不要这样做。
如果您的状态值不仅仅是 {position: ?}
,那么这个版本应该可以解决问题:
const reshape = (state, key, pos = state[key].position) => dissoc(key, map(
({position, ...rest}) => position > pos
? {position: position - 1, ...rest}
: {position, ...rest},
state
))
或者,正如 Emi 指出的那样,这个版本的性能可能更高:
const reshape = (state, key, pos = state[key].position) => dissoc(key, map(
(obj) => obj.position > pos ? {...obj, position: obj.position - 1} : obj,
state
))