0

Using plain JavaScript or lodash, what's the easiest way to transform an array of objects into a single object, while concatenating any array values?

I can achieve it on a single property using _.flatMap(before, "nodes") but not sure how to include all properties.

For example:

const before = [
  {
    nodes: [
      { "id": "1" },
      { "id": "2" }
    ],
    links: [
      { "source": "1", "target": "2" }
    ],
  },
  {
    nodes: [
        { "id": "3" },
        { "id": "4" },
        { "id": "5" },
        { "id": "6" }
    ],
    links: [
      { "source": "3", "target": "4" },
      { "source": "5", "target": "6" }
    ],
  }
];

const after = {
  nodes: [
    { "id": "1" },
    { "id": "2" },
    { "id": "3" },
    { "id": "4" },
    { "id": "5" },
    { "id": "6" }
  ],
  links: [
    { "source": "1", "target": "2" },
    { "source": "3", "target": "4" },
    { "source": "5", "target": "6" }
  ],
};
3
  • What do you mean "include all properties"? Do you know specific keys in the object, like nodes and links, or are you asking how to merge properties of any two objects together? Commented Jun 19, 2023 at 5:18
  • @AndyRay yes, in this case, I do know the specific property keys, however I'm looking for a general solution that'll merge all properties. Commented Jun 19, 2023 at 6:56
  • What does “merge all properties” mean? Do you already know your object only has array values? If not, what is your expectation for merging non-array values? And what about nested objects and arrays? Commented Jun 19, 2023 at 16:20

5 Answers 5

1

You can achieve this using vanilla js using reduce and Object.entries as:

const before = [
    {
        nodes: [
            { "id": "1" },
            { "id": "2" }
        ],
        links: [
            { "source": "1", "target": "2" }
        ],
    },
    {
        nodes: [
            { "id": "3" },
            { "id": "4" },
            { "id": "5" },
            { "id": "6" }
        ],
        links: [
            { "source": "3", "target": "4" },
            { "source": "5", "target": "6" }
        ],
    }
];

const result = before.reduce((acc, curr) => {
    Object.entries(curr).forEach(([key, value]) => {
        acc[key] = [ ...(acc[key] ?? []), ...value];
    })
    return acc;
}, {});

console.log(result);

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

Comments

1

Since you want to merge array into one, you should use reduce instead of map. Following should work

after = before.reduce((prevResult, element) => {
    var newResult = {}
    Object.keys(element).forEach((key) => {
        newResult[key] = prevResult[key].concat(element[key])
    })
    return newResult
})

reduce will work with each element in iterative manner from left to right.

Hope this helps

Comments

1

One possible solution using lodash:

const after = _.reduce(before, (acc, curr) => {
  _.forOwn(curr, (value, key) => {
    acc[key] = _.concat(acc[key] || [], value);
  });
  
  return acc;
}, {});

The result is a new object that contains these combined arrays.

Comments

1
const before = [
  {
    nodes: [
      { "id": "1" },
      { "id": "2" }
    ],
    links: [
      { "source": "1", "target": "2" }
    ],
  },
  {
    nodes: [
        { "id": "3" },
        { "id": "4" },
        { "id": "5" },
        { "id": "6" }
    ],
    links: [
      { "source": "3", "target": "4" },
      { "source": "5", "target": "6" }
    ],
  }
];

Following below code:

const flatData = (data) => {
    const result = { nodes : [], links: [] };

    for (let i = 0; i < data.length; i++) {
        const {nodes, links} = data[i]; // nodes and links

        // nodes
        for (let i = 0; i < nodes.length; i++) {
            result.nodes = [...result.nodes, nodes[i]];
        }

        // links
        for (let i = 0; i < links.length; i++) {
            result.links = [...result.links, nodes[i]];
        }
    }

    return result;
}

Comments

1

You can use Array.reduce() to achieve this efficiently.

Please find the following code:

const before = [{
    nodes: [{
        "id": "1"
      },
      {
        "id": "2"
      }
    ],
    links: [{
      "source": "1",
      "target": "2"
    }],
  },
  {
    nodes: [{
        "id": "3"
      },
      {
        "id": "4"
      },
      {
        "id": "5"
      },
      {
        "id": "6"
      }
    ],
    links: [{
        "source": "3",
        "target": "4"
      },
      {
        "source": "5",
        "target": "6"
      }
    ],
  }
];

const after = before.reduce((acc, curr) => {
    Object.keys(curr).forEach(key => {
        acc[key] = [...acc[key] , ...curr[key]]
    })
    return acc;
})
console.log("After is ===>>", after);

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.