Как преобразовать карту объекта в массив с Рамдой? - PullRequest
1 голос
/ 24 апреля 2019

Я бы хотел перевести из следующего объекта:

{
  'id-1': { prop: 'val1' },
  'id-2': { prop: 'val2' },
}

В массив:

[
  { id: 'id-1', prop: 'val1' },
  { id: 'id-2', prop: 'val2' },
]

Что я сделал до сих пор (это работает):

R.pipe(
  R.toPairs,
  R.map(([id, props]) => ({
    id,
    ...props,
  }))
)

Я бы хотел решить ее, используя только Рамду - если это возможно.

Ответы [ 2 ]

3 голосов
/ 24 апреля 2019

Я бы предположил, что решение этой проблемы "с использованием только Ramda" является плохой целью проектирования, если только это не упражнение в изучении Ramda. Я один из основателей Ramda и большой поклонник, но Ramda - это всего лишь инструментарий, предназначенный для упрощения вашего кода и упрощения работы в определенной парадигме.

Тем не менее, мы могли бы написать бессмысленную версию этого, используя Ramda. Первое, что приходит мне в голову, это *:

const transform = pipe(
  toPairs,
  map(apply(useWith(merge, [objOf('id'), identity])))
)

const data = {'id-1': { prop: 'val1' }, 'id-2': { prop: 'val2'}}

console.log(transform(data))
<script src="https://bundle.run/ramda@0.26.1"></script><script>
const {pipe, toPairs, map, apply, useWith, merge, objOf, identity} = ramda    </script>

Но это меньше для чтения, чем ваш оригинал, не больше.

Этот код:

const transform = pipe(
  toPairs,
  map(([id, props]) => ({...props, id}))
)

кристально чист, в то время как для этой версии Ramda требуется, чтобы она понимала специфичные для Ramda useWith и objOf и немного неясные apply - я надеюсь, что map, merge и identity ясно.

На самом деле, этот код достаточно прост, чтобы я мог написать его как однострочный, и в этом случае я переключаюсь на compose на pipe:

const transform = compose(map(([id, props]) => ({...props, id})), toPairs)

Но я, вероятно, не стал бы этого делать, так как эту многострочную pipe версию легче читать.

Наконец, обратите внимание, что мы можем сделать это довольно читабельным способом без каких-либо инструментов Ramda вообще:

const transform = (data) => 
  Object.entries(data).map(
    ([id, props]) => ({...props, id})
  )

Если бы я уже использовал Ramda в своей базе кода, я бы предпочел версию pipe, указанную выше; Я думаю, что это несколько легче читать. Но никогда бы не внедрил Рамду в проект только из-за этой незначительной разницы.

Я волнуюсь, что люди делают фетиш из-за бессмысленного кода. Это инструмент. Используйте его, когда он делает ваш код более понятным. Пропустите его, когда он сделает ваш код более неясным. Здесь я думаю, что вы начинаете с вполне читаемого кода; это трудно улучшить.


* Обратите внимание , что identity здесь не является строго обязательным; Вы можете пропустить это без вреда. Функция, сгенерированная useWith без этого identity, будет некорректно сообщать арность 1, но так как функция сразу оборачивается apply и затем помещается в контекст получения массива из двух элементов из toPairs , нет ничего, что зависит от этого. Но я считаю хорошей привычкой включать это независимо.

1 голос
/ 26 апреля 2019

что по этому поводу? вероятно, менее многословно!

const toArray = R.pipe(
  R.toPairs,
  R.map(
    R.apply(R.assoc('id')),
  ),
);

const data = {
  'id-1': { prop: 'val1' },
  'id-2': { prop: 'val2' },
};

console.log('result', toArray(data));
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
...