2

Given an array of objects:

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

What is the most elegant way of converting it into the following structure - essentially and array of the ids along with a map of the objects:

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

I did this using underscore (see below or my codepen), but is there a better way? For example can this be done in a more declarative way using functional programming? Is there a way to genericize the code to work on an array of any type of objects?

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));

3 Answers 3

4

If you're just interested in the second example from @jeremija, then Ramda has a function built-in for this, indexBy, which you can use like this:

R.indexBy(R.prop('id'), projects);
Sign up to request clarification or add additional context in comments.

2 Comments

That's indeed short and sweet. Thanks for sharing, @ScottSauyet.
This is actually the most functional way
2

Using the new arrow functions, and the map & reduce Array methods, you can further simplify this:

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;
    }, {})
};

Or maybe having an array of IDs is not necessary as you can easily get just the keys:

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

var projectIds = Object.keys(projectMap);

Comments

1

VanillaJS implementation:

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

Or even simpler with reduce:

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

We start here from empty hash {}, and extend carry(c) with new project(p) on each reduce iteration.

1 Comment

love your answer! I wish I can mark both yours and jeremija's as correct - as they are both aiming at the same approach (just that the style is slightly different). However, given only one choice, I am marking jeremija's as correct for suggesting that I don't need the array of ids in the result - it can be derived from the map. However, I am upvoting your answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.