Как превратить список объектов в массив / объект с ключами? - PullRequest
5 голосов
/ 08 октября 2019

Я пытаюсь написать код, используя Ramda для создания новой структуры данных, используя только ключи id и comment исходных объектов. Я новичок в Ramda, и он дает мне некоторые припадки, хотя у меня есть опыт работы с тем, что я считаю похожим кодированием с Python.

Учитывая следующую исходную структуру данных…

const commentData = {
  '30': {'id': 6, 'comment': 'fubar', 'other': 7},
  '34': {'id': 8, 'comment': 'snafu', 'other': 6},
  '37': {'id': 9, 'comment': 'tarfu', 'other': 42}
};

Iхочу преобразовать его в этот…

{
  '6': 'fubar',
  '8': 'snafu',
  '9': 'tarfu'
}

Я нашел следующий пример в кулинарной книге Ramda , который подходит близко ...

const objFromListWith = R.curry((fn, list) => R.chain(R.zipObj, R.map(fn))(list));
objFromListWith(R.prop('id'), R.values(commentData));

Но возвращаемые значения включают в себявесь исходный объект как значения…

{
  6: {id: 6, comment: "fubar", other: 7},
  8: {id: 8, comment: "snafu", other: 6},
  9: {id: 9, comment: "tarfu", other: 42}
}

Как можно уменьшить значения до значения только их ключа comment?

Я не нужно , чтобы использовать код, который я получил из поваренной книги. Если кто-нибудь может предложить какой-нибудь код, который даст результаты, которые я ищу, также лучше (проще, короче или эффективнее), чем приведенный здесь пример, я буду рад использовать его вместо этого.

Ответы [ 2 ]

6 голосов
/ 08 октября 2019

Если вы не возражаете, вам не нужно использовать Ramda для этого, чистый JS может с этим справиться:

Вы можете использовать комбинацию Object.values(), чтобы получить все значения вашегопервый объект (commentData) и .forEach() (или даже .map(), но медленнее) в массиве, который получается в результате Object.values для динамического вставления значений в новый объект.

const commentData = {
  '30': {'id': 6, 'comment': 'fubar', 'other': 7},
  '34': {'id': 8, 'comment': 'snafu', 'other': 6},
  '37': {'id': 9, 'comment': 'tarfu', 'other': 42}
};

let values = Object.values(commentData)
let finalObj = {};

values.forEach(x => finalObj[x.id] = x.comment)

console.log(finalObj)

Но, если вам нужен однострочный, вы можете пойти с Object.fromEntries() после возврата массивов ключ / значение из .map() на основе id и comment, как показано ниже:

const commentData = {
  '30': {'id': 6, 'comment': 'fubar', 'other': 7},
  '34': {'id': 8, 'comment': 'snafu', 'other': 6},
  '37': {'id': 9, 'comment': 'tarfu', 'other': 42}
};

console.log(Object.fromEntries(Object.values(commentData).map(x => [x.id, x.comment])))
4 голосов
/ 08 октября 2019

Один вкладыш Рамда будет

const foo = compose(fromPairs, map(props(['id', 'comment'])), values)

const commentData = {
  '30': {'id': 6, 'comment': 'fubar', 'other': 7},
  '34': {'id': 8, 'comment': 'snafu', 'other': 6},
  '37': {'id': 9, 'comment': 'tarfu', 'other': 42}
}

console.log(
  foo(commentData)
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script>const {compose, fromPairs, map, props, values} = R           </script>

Но это не кажется намного чище, чем (небольшая поправка) к предложению в комментарии epascarello:

const foo = (obj) => 
  Object.values(obj).reduce((o, v) => (o[v.id] = v.comment) && o, {})

илипохожую версию я бы написал, если бы она не вызывала проблем с производительностью:

const foo = (obj) => 
  Object.values(obj).reduce((o, {id, comment}) => ({...o, [id]: comment}), {})
...