JavaScript - 将数组转换为地图

JavaScript - Converting arrays to maps

给定一个对象数组:

var projects = [
    {
        id: 1,
        name: 'Trader Portal'
    },
    {
        id: 2,
        name: 'Risk Engine'
    },
];

将其转换为以下结构的最优雅方法是什么 - 本质上是 ID 数组以及对象映射:

{
    projects: [
        1,
        2
    ],
    projectMap: {
        1: {
            id: 1,
            name: 'Trader Portal'
        },
        2: {
            id: 2,
            name: 'Risk Engine'
        }
    }
}

我是用下划线做的(见下文或我的 codepen),但有更好的方法吗?例如,这可以使用函数式编程以更具声明性的方式完成吗?有没有办法通用化代码以处理任何类型对象的数组?

var projects = [
    {
        id: 1,
        name: 'Trader Portal'
    },
    {
        id: 2,
        name: 'Risk Engine'
    },
];

var result = {};

result.projects = _.map(projects, function(project) {
  return project.id;
});

result.projectMap = {};
_.each(projects, function(project) {
  result.projectMap[project.id] = project;
});

console.log(JSON.stringify(result));

使用新的箭头函数和 map & reduce 数组方法,您可以进一步简化:

var projects = [
    {
        id: 1,
        name: 'Trader Portal'
    },
    {
        id: 2,
        name: 'Risk Engine'
    },
];

var projectMap = {
    projects: projects.map(p => p.id),
    projectMap: projects.reduce((obj, p) => {
      obj[p.id] = p;
      return obj;
    }, {})
};

或者也许不需要 ID 数组,因为您可以轻松地只获取键:

var projectMap = projects.reduce((obj, p) => {
    obj[p.id] = p;
    return obj;
}, {});

var projectIds = Object.keys(projectMap);

VanillaJS 实现:

var result = {projectMap: {}};
result.projects = projects.map(p => p.id);
projects.forEach(p => {
  result.projectMap[p.id] = p;
});

或者使用 reduce 更简单:

result.projectMap = projects.reduce((c, p) => (c[p.id] = p, c), {});

我们从空哈希 {} 开始,并在每次 reduce 迭代时用新项目 (p) 扩展 carry(c)。

如果您只对 @jeremija, then Ramda has a function built-in for this, indexBy, which you can use like this 中的第二个示例感兴趣:

R.indexBy(R.prop('id'), projects);