1

Sorry about the title. I don't even know how I can explain what I want.

So here is what I am trying to achieve

const array = [
  {
    key: 0,
    key2: [ { id: "a", data: "abc" }, { id: "b", data: "wxy" }... ]
  },
  {
    key: 1,
    key2: [ { id: "a", data: "qwe" }, { id: "b", data: "zxc" }... ]
  },
...
]

I want to convert it to,

const result = {
    0 : {
        a: "abc",
        b: "wxy"
    },
    1 : {
        a: "qwe",
        b: "zxc"
    }
}

so far, I have this:

  const transforms = array
    .map((o) => {
      return { [o.key]: o.key2 };
    })
    .reduce((prev, curr) => {
      for (let key in curr)
        prev[key] = curr[key]
          .map((c) => {
            return { [c.id]: c.data};
          })
          .reduce((prev, curr) => {
            for (let key in curr) prev[key] = curr[key];
            return prev;
          }, {});

      return prev;
    }, {});

Which is hard to read, and probably not very performant. To be honest, I don't even know if it is really 100% working. It gave me expected result so far.

How do I refactor this? Please help.

2
  • Probably a better question for codereview.stackexchange.com. Though please make sure you read their help first Commented Jul 7, 2020 at 8:11
  • Didn't know that one, I will try there! Commented Jul 7, 2020 at 8:15

2 Answers 2

4

Your task may be effectively decomposed into 4 tiny problems:

key2.map(({id,data}) => ({[id]:data}))
  • Combine those key/value pairs into a single object, using Object.assign()
Object.assign({}, ...key2.map(({id,data}) => ({[id]:data})))
src.map(({key2}) => 
        Object.assign({}, ...key2.map(({id,data}) => ({[id]:data}))))
  • destructure resulting array (which is essentially, an object) into the object
{...result} = src.map(({key2}) => 
        Object.assign({}, ...key2.map(({id,data}) => ({[id]:data}))))
      

Resulting code is way more compact and works noticeably faster

You may find the live-demo as follows:

const src = [{key:0,key2:[{id:"a",data:"abc"},{id:"b",data:"wxy"}]},{key:1,key2:[{id:"a",data:"qwe"},{id:"b",data:"zxc"}]}],

      {...result} = src.map(({key2}) => 
        Object.assign({}, ...key2.map(({id,data}) => ({[id]:data}))))
      
console.log(result)
.as-console-wrapper{min-height:100%;}

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

Comments

0

const array = [
    {
      key: 0,
      key2: [ { id: "a", data: "abc" }, { id: "b", data: "wxy" }]
    },
    {
      key: 1,
      key2: [ { id: "a", data: "qwe" }, { id: "b", data: "zxc" }]
    },

]

const result = array.reduce((res, entry) => {
    return Object.assign(res, { [entry.key]: entry.key2.reduce((data, current) => {
        return Object.assign(data, { [current.id]: current.data }) 
    }, {}) });
}, {})

console.log(result)

Conversion function

array.reduce((res, entry) => {
    return Object.assign(res, { [entry.key]: entry.key2.reduce((data, current) => {
        return Object.assign(data, { [current.id]: current.data }) 
    }, {}) });
}, {})

2 Comments

See my comments on the above answer
You could've made your code a bit more compact by getting rid of unnecessary return's and curly braces. Also, considering OP's concern about performance, your solution does not provide that much of a gain.

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.