1

for example, from this:

const items = [
        {
            "id": 3,
            "orgId": 2,
            "mod": "toyota",
            "part": "wheel",
            "price": 333
        },
        {
            "id": 4,
            "orgId": 2,
            "mod": "toyota",
            "part": "shell",
            "price": 350
        },
        {
            "id": 9,
            "orgId": 2,
            "mod": "honda",
            "part": "wheel",
            "price": 222
        },
        {
            "id": 10,
            "orgId": 2,
            "mod": "honda",
            "part": "shell",
            "price": 250
        }
    ]


and convert to:


items = {
    "toyota": {"wheel": 333, "shell": 350 }, 
    "honda": {"wheel": 222, "shell": 250 }
}

What is the most elegant way?

I was trying to use .map() but I'm not sure how to complete the nested struture.


Follow up:

Using this method:

      const structure = {};
      prices.forEach((e) => {
       structure[e.mod] ??= {};
       structure[e.mod][e.part] = e.price;
      });

or:

      result = items.reduce((r, o) => {
        r[o.mod] ??= {};
        r[o.mod][o.part] = o.price;
        return r;
      },{});

I got the following error:

Module parse failed: Unexpected token (56:31)
File was processed with these loaders:
 * ./node_modules/@pmmmwh/react-refresh-webpack-plugin/loader/index.js
 * ./node_modules/react-scripts/node_modules/babel-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.
|       const structure = {};
|       prices.forEach(e => {
>         structure[e.mod] ??= {};
|         structure[e.mod][e.part] = e.price;
|       });

I have done quite a lot searching but cannot find how to solve it.

Any advices?

Kid_Learning_C
  • 2,605
  • 4
  • 39
  • 71
  • Familiarize yourself with [how to access and process nested objects, arrays or JSON](/q/11922383/4642212) and how to [create objects](//developer.mozilla.org/docs/Web/JavaScript/Reference/Operators/Object_initializer) and use the available static and instance methods of [`Object`](//developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object#Static_methods) and [`Array`](//developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array#Static_methods). What have you tried with `.map`? This sounds more like a job for `reduce` (or a `forEach` which adds onto an object). – Sebastian Simon Aug 17 '21 at 19:23
  • 1
    What should happen in case of duplicate records ? – MaxZoom Aug 17 '21 at 19:29
  • @MaxZoom Override – Kid_Learning_C Aug 19 '21 at 17:58

4 Answers4

4

You can use array#reduce to group based on mod.

const items = [ { "id": 3, "orgId": 2, "mod": "toyota", "part": "wheel", "price": 333 }, { "id": 4, "orgId": 2, "mod": "toyota", "part": "shell", "price": 350 }, { "id": 9, "orgId": 2, "mod": "honda", "part": "wheel", "price": 222 }, { "id": 10, "orgId": 2, "mod": "honda", "part": "shell", "price": 250 } ],
      result = items.reduce((r, o) => {
        r[o.mod] ??= {};
        r[o.mod][o.part] = o.price;
        return r;
      },{});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Hassan Imam
  • 21,956
  • 5
  • 41
  • 51
2

You could use the code below:

const transformedItems = items.reduce((acc, item) => {
  acc[item.mod] = { ...acc[item.mod], [item.part]: item.price }
  return acc
}, {})

console.log(transformedItems)
  • Thank you for the great answer! Could you please take a look at the follow-up question: https://stackoverflow.com/questions/68850278/typescript-type-null-cannot-be-used-as-an-index-type-in-array-reduce-accumu? If this is running in Typescript, it shows an error. – Kid_Learning_C Aug 19 '21 at 15:07
0

I think the most confortable structure will be this

items = {
    "toyota": {"wheel": 333, "shell": 350 }, 
    "honda": {"wheel": 222, "shell": 250 }
}

because you make sure to get unique elements

const items = [{
  "id": 3,
  "orgId": 2,
  "mod": "toyota",
  "part": "wheel",
  "price": 333
}, {
  "id": 4,
  "orgId": 2,
  "mod": "toyota",
  "part": "shell",
  "price": 350
}, {
  "id": 9,
  "orgId": 2,
  "mod": "honda",
  "part": "wheel",
  "price": 222
}, {
  "id": 10,
  "orgId": 2,
  "mod": "honda",
  "part": "shell",
  "price": 250
}];

const structure = {};
items.forEach((e) => {
 structure[e.mod] ??= {};
 structure[e.mod][e.part] = e.price;
});

console.log(structure)
  • Thank you very much. I have got a `Module parse failed: Unexpected token (56:31)` error using `structure[e.mod] ??= {};` ( see the updated post). Could you please comment? – Kid_Learning_C Aug 19 '21 at 17:05
0

You could also iterate through items and populate the result object as below:

const items = [ { "id": 3, "orgId": 2, "mod": "toyota", "part": "wheel", "price": 333 }, { "id": 4, "orgId": 2, "mod": "toyota", "part": "shell", "price": 350 }, { "id": 9, "orgId": 2, "mod": "honda", "part": "wheel", "price": 222 }, { "id": 10, "orgId": 2, "mod": "honda", "part": "shell", "price": 250 } ];

const result = {};
items.forEach((e) => {
  result[e.mod] = {...result[e.mod], [e.part]: e.price};
});

console.log(result);
MaxZoom
  • 7,619
  • 5
  • 28
  • 44