0

I have an object that originally looks like this

{
  foo: {
    fruit: "watermelon",
    vege: "celery",
  },
  bar: {
    fruit: "banana",
    candy: "snickers",
    drink: "coke",
  },
  ...
}

but want to "flatten" and have it look like this

{
  fruit: "banana",
  vege: "celery",
  candy: "snickers",
  drink: "coke",
}

If there's an overlap in the sub-object keys, just overwrite the previous one.

What's a sane way to do this?

5 Answers 5

4

You can grab the values of your object using Object.values(), and then use Object.assign() with the spread syntax to merge all the objects together:

const obj = { foo: { fruit: "watermelon", vege: "celery", }, bar: { fruit: "banana", candy: "snickers", drink: "coke", } };

const res = Object.assign({}, ...Object.values(obj));
console.log(res);

With lodash you can use the corresponding methods _.assign() and _.values():

const obj = { foo: { fruit: "watermelon", vege: "celery", }, bar: { fruit: "banana", candy: "snickers", drink: "coke", } };

const res = _.assign({}, ..._.values(obj));
console.log(res);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>

Both of these methods rely on the iteration order that Object.values() and for...in uses. In the latest spec this is something which can be relied on, but this hasn't always been the case. If you need to read the values in a guaranteed order 100% of the time, you can consider specifying the order of keys using an array:

const obj = { foo: { fruit: "watermelon", vege: "celery", }, bar: { fruit: "banana", candy: "snickers", drink: "coke", } };

const order = ["foo", "bar"]; // visit foo first then bar
const res = Object.assign({}, ...order.map(k => obj[k]));
console.log(res);

Sign up to request clarification or add additional context in comments.

Comments

1

With lodash you can use _.values() that generates an array, and then spread to _.merge(). I'm using _.flow() to generate a function that does that:

const fn = _.flow(_.values, _.spread(_.merge))

const obj = {
  foo: {
    fruit: "watermelon",
    vege: "celery",
  },
  bar: {
    fruit: "banana",
    candy: "snickers",
    drink: "coke",
  },
}

const result = fn(obj)

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js" integrity="sha512-90vH1Z83AJY9DmlWa8WkjkV79yfS2n2Oxhsi2dZbIv0nC4E6m5AbH8Nh156kkM7JePmqD6tcZsfad1ueoaovww==" crossorigin="anonymous"></script>

Comments

0

You can get values of object using Object.prototype.values and using Array.prototype.forEach, you can get the merge the object [key, value] pairs as follows.

const input = {
  foo: {
    fruit: "watermelon",
    vege: "celery",
  },
  bar: {
    fruit: "banana",
    candy: "snickers",
    drink: "coke",
  }
};

let output = {};
Object.values(input).forEach((item) => {
  output = {
    ...output,
    ...item
  };
});
console.log(output);

Comments

0

const input = {
  foo: {
    fruit: "watermelon",
    vege: "celery",
  },
  bar: {
    fruit: "banana",
    candy: "snickers",
    drink: "coke",
  },
}

var result = {}
Object.values(input).forEach(item => {
  result = {
    ...result,
    ...item
  }
});
console.log(result)

Comments

0

You could take two function for getting a flat object from multi nested objects.

The outer gets from an array of objects a flat object and the recursinve function returns a flat array with object for every level.

const
    flat = data => Object.assign({}, ...pairs(data)),
    pairs = o => o && typeof o === 'object' && Object
        .entries(o)
        .flatMap(([k, v]) => pairs(v) || { [k]: v }),
    data = { 
        foo: {
            fruit: "watermelon",
            vege: "celery"
        },
        bar: {
            fruit: "banana",
            candy: "snickers",
            drink: "coke"
        },
        n: {
            m: {
                o: {
                    p: 42
                }
            }
        }
    },
    result = flat(data);

console.log(result);

Comments

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.