Уменьшить "положение" собственности с Рамдой - PullRequest
0 голосов
/ 22 января 2019

С этим объектом:

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},
}

Порадевшись с Рамдой, я закончил примерно так:

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')

Это работает, но я не совсем доволенэто потому что я нахожу это немного многословным.Как вы думаете, есть лучший способ написать это?

Ответы [ 4 ]

0 голосов
/ 22 января 2019

Я бы, наверное, сделал что-то вроде этого:

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>

Обратите внимание, что обсуждение между Ниной и customcommander о remove имеет отношение здесь. Эта версия не меняет ваш оригинал. Рамда никогда не делает этого.

Если ваши значения состояния больше, чем просто {position: ?}, то эта версия должна помочь:

const reshape = (state, key, pos = state[key].position) => dissoc(key, map(
  ({position, ...rest}) => position > pos 
    ? {position: position - 1, ...rest} 
    : {position, ...rest},
  state
))

Или, как отмечает Эми, эта версия, вероятно, будет более производительной:

const reshape = (state, key, pos = state[key].position) => dissoc(key, map(
  (obj) => obj.position > pos ? {...obj, position: obj.position - 1} : obj,
  state
))
0 голосов
/ 22 января 2019

Рамда решение, которое использует линзы :

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>
0 голосов
/ 22 января 2019

Я бы немного разбил вещи:

Во-первых, функция, которая возвращает функцию, которая проверяет, имеет ли объект {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>
0 голосов
/ 22 января 2019

Просто отфильтруйте и обновите.Затем удалите.

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);
...