3

I have an object that contains other objects, such as:

let foo = {
  a: {
    b: {},
    c: {}
  },
  d: {
    e: {}
  }
};

Now I want to transform this into an array of objects, where the keys of the first two levels form a key / value pair, such as:

let transformedFoo = [
  { outer: 'a', inner: 'b' },
  { outer: 'a', inner: 'c' },
  { outer: 'd', inner: 'e' }
];

My current approach looks like this:

let fooTransformed = [];

Object.keys(foo).forEach(function (outerKey) {
  Object.keys(foo[outerKey]).forEach(function (innerKey) {
    fooTransformed.push({
      outer: outerKey,
      inner: innerKey
    });
  });
});

It works, but I think it's not "nice" (i.e., it's not nice to have two nested loops). Is there a better way on how to achieve this (I could imagine that there is a quite elegant purely functional solution, but I can't think of any)?

3
  • 2
    it seems that your approach is the accepted one. Commented Jan 27, 2015 at 20:44
  • 2
    Logically, nested manipulation would require another nested loop (or conditional). A "functional" approach would just hide this fact from view. Commented Jan 27, 2015 at 20:46
  • 1
    @DavidPullar is right, instead of a nested loop, you'll have a nested map, plus a reduce to flatten out the results. See below Commented Jan 27, 2015 at 21:02

1 Answer 1

2

Using map and reduce:

> Object.keys(foo).map(function(key) { 
      return Object.keys(foo[key]).map(function(val) {
          return {outer: key, inner: val} } ) 
      }).reduce(function(a,b) { return a.concat(b) })

[ { outer: 'a', inner: 'b' },
  { outer: 'a', inner: 'c' },
  { outer: 'd', inner: 'e' } ]
Sign up to request clarification or add additional context in comments.

3 Comments

you can improve on this and retain the original two loops if you combine the first map with the last reduce. Object.keys(foo).reduce(function(reduced, key) { return reduced.concat(Object.keys(foo[key]).map(function(val) { return {outer: key, inner: val} } )) }, []);
It works, and it is a functional approach, hence I accepted it and +1ed it. Anyway, I'm going to stick with my original version, though ;-)
It's good to try and see if other approaches offer something really beneficial. Your approach is much clearer what is going on.

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.