将 Object 中的数组 属性 扩展为多个 Object 填充数组值

Expand Array property in Object to Multiple Objects populated w/ Array value

这个问题的标题很糟糕,但很难用语言表达,下面的例子有望解决问题。

我仍在学习 Ramda 的更高级功能,并且大部分时间都在尝试在 Ramda 中使这种转换更加简洁,但 ES6 版本仍然感觉更具可读性和简短性。

我希望 Ramda 高手可以帮助以更好的方式表达这个功能,使用更少的功能,也许更短。

有没有更好的方法用 Ramda 或纯 JS 来写这个?
谢谢!

更新: 向 objects 添加了一些额外的属性,目的是在 objects.[=15 的新数组中保持这些属性完好无损=]

Link to Ramda 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>

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"
  }
]

在 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;
    }, []);
}

这里是 fiddle.

说明: 你想要的是一个对象数组(因此 reduce 来收集结果),这些对象是由 map 在类型上构建的集合构建的。

我对 RamdaJS 一无所知

通过查看文档,使用 R.Reduce and R.map 的 Ramda 转换应该是直接的。

为了获取类型,您可以利用 pluck.

我不擅长 Ramda,但在 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 看起来会稍微好一点。

这是使用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));

希望对您有所帮助。