Разверните свойство Array в Object до нескольких объектов, заполненных значением Array - PullRequest
0 голосов
/ 25 августа 2018

Этот заголовок вопроса ужасен, но его трудно выразить словами, надеюсь, следующий пример прояснит ситуацию.

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

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

Есть ли лучший способ написать это на Ramda или обычном JS?
Спасибо!

Обновление: добавлены некоторые дополнительные свойства к объектам, поскольку предполагается сохранить их в новом массиве объектов.

Ссылка на Рамда REPL

// For every type in bundle.types creates a new bundle obj.

const bundles = [
  {
    name: 'banana',
    input: 'src/banana.js',
    dir: 'dist',
    types: ['esm', 'umd']
  },
  {
    name: 'apple',
    input: 'src/apple.js',
    dir: 'dist',
    types: ['umd']
  }
]

/* =>
[
  {
    name: 'banana',
    input: 'src/banana.js',
    dir: 'dist',
    type: 'esm'
  },
  {
    name: 'banana',
    input: 'src/banana.js',
    dir: 'dist',
    type: 'umd'
  },
  {
    name: 'apple',
    input: 'src/apple.js',
    dir: 'dist',
    type: 'umd'
  }
]
*/

let allBundles = R.chain(R.converge(
  R.pipe(R.xprod, R.map(R.mergeAll)),
  [
    R.pipe(R.dissoc('types'), R.of),
    R.pipe(R.prop('types'), R.map(R.objOf('type')))
  ]
), bundles);

console.log('ramda');
console.log(JSON.stringify(allBundles, null, 2));

allBundles = bundles.reduce((acc, b) => {
  return acc.concat(b.types.map((type) => {
    const bundle = { ...b, type };
    delete bundle.types;
    return bundle;
  }));
}, []);

console.log('lamda')
console.log(JSON.stringify(allBundles, null, 2));
<script src="https://cdn.jsdelivr.net/npm/ramda@0.25.0/dist/ramda.min.js"></script>

Ответы [ 4 ]

0 голосов
/ 25 августа 2018

Это идеальное место для использования R.chain:

const bundles = [ { name:  "banana"
                  , input: "src/banana.js"
                  , dir:   "dist"
                  , types: ["esm", "umd"]
                  }
                , { name:  "apple"
                  , input: "src/apple.js"
                  , dir:   "dist"
                  , types: ["umd"]
                  }
                ];

const unbundle = ({ types, ...rest }) =>
    types.map(type => ({ ...rest, type }));

const unbundleAll = R.chain(unbundle);

console.log(JSON.stringify(unbundleAll(bundles), null, 2));
<script src="https://cdn.jsdelivr.net/npm/ramda@0.25.0/dist/ramda.min.js"></script>

Вот то же самое в ванильном JS:

const bundles = [ { name:  "banana"
                  , input: "src/banana.js"
                  , dir:   "dist"
                  , types: ["esm", "umd"]
                  }
                , { name:  "apple"
                  , input: "src/apple.js"
                  , dir:   "dist"
                  , types: ["umd"]
                  }
                ];

const unbundle = ({ types, ...rest }) =>
    types.map(type => ({ ...rest, type }));

const concatMap = f => xs => [].concat(...xs.map(f));

const unbundleAll = concatMap(unbundle);

console.log(JSON.stringify(unbundleAll(bundles), null, 2));

Надеюсь, это поможет.

0 голосов
/ 25 августа 2018

В JS я бы пошел на:

const bundles = [
    {
        name: 'banana',
        types: ['esm', 'umd']
    },
    {
       name: 'apple',
       types: ['umd']
    }
];

const expanded = (arr) => {
    return arr.reduce((o,n)=>{
     let result = n.types.map((t)=>{
      return {name:n.name, type:t}
     });
     o = [...o,...result];
     return o;
    }, []);
}

Вот скрипка .

Пояснение: Вам нужен массив объектов (следовательно, reduce для сбора результата), которые создаются коллекцией, созданной из map для типов.

Я не знаю о RamdaJS

Посмотрев документацию, трансформация с Рамдой с использованием R.Reduce и R.map должна быть прямой.

Чтобы получить типы, вы можете использовать pluck .

0 голосов
/ 25 августа 2018

Я не очень хорош в Рамде, но в JS вижу потенциал:

const allBundles = bundles.reduce(
    (acc, { types, ...attrs}) => 
        [...acc, ...types.map((type) => ({...attrs, type }))], []);

const bundles = [
    { name: 'banana', types: ['esm', 'umd'] }, 
    { name: 'apple', types: ['umd'] },
];

console.log('lamda')
console.log(JSON.stringify(allBundles, null, 2));
<script src="https://cdn.jsdelivr.net/npm/ramda@0.25.0/dist/ramda.min.js"></script>

Это выглядело бы немного лучше с flaMap.

0 голосов
/ 25 августа 2018
const bundles = [
    { name: 'banana', types: ['esm', 'umd'] },
    { name: 'apple', types: ['umd'] }
];

let newArray = [];
bundles.forEach(bundle => {
    bundle.types.map(type => {
      newArray.push({ name: bundle.name, type })
    });
});
console.log(newArray);

This will output =>
[
  {
   "name": "banana",
   "type": "esm"
  },
  {
    "name": "banana",
    "type": "umd"
  },
  {
    "name": "apple",
    "type": "umd"
  }
]
...