0

I have an observable output like below. I want to convert this data to desired format(proivded below). I am partially successful forming key value pairs but couldn't figure out how to send only one field(that is for which selected is true) from the cars array to final output.

***Observable Output****

[{
  "name":"John",
  "age":30,
  "cars": [
      { "selected":true,  "name":"Ford", "models": "Mustang"},
      { "selected":false, "name":"BMW", "models": "320" },
      { "selected":true, "name":"Fiat", "models":"500" }
  ]
 },
 {
  "name":"alex",
  "age":40,
  "cars": [
      { "selected":true,  "name":"tesla", "models": "x"},
      { "selected":false, "name":"merc", "models": "300" },
      { "selected":true, "name":"honda", "models":"accord" }
   ]
  }
]

****Desired Format*****

{John:[ford, fiat], Alex:[tesla,honda]} 

***Code used*****

const results = item.reduce((r,{name,cars}) => (r[name]=cars,r), {})

//This gives me complete cars object but i need only name from it(and that too for selected true ones).

Edit 1: Do not want to have empty record in the final object. For eg, if Alex does not have any Cars Selected True then i do not want Alex:[] in the final object.

3
  • 1
    const results = data.reduce((r,{name,cars}) => (r[name]=cars.filter(ch => ch.selected).map(ch => ch.name),r), {}); maybe something like this? Commented May 30, 2020 at 0:44
  • @Halili Cakar. Thanks, this works like a charm. What if i want to return 'r' only if has atleast one value. For Eg, In the above example for Alex if none of the cars have selected true then results shouldn't have Alex record. Commented May 30, 2020 at 1:24
  • Hey @Raji i'm glad it worked for you. If you want to filter the results that have only cars on, you might wanna filter first and reduce it with this function again. So try this; data.filter(ch => ch.cars.some(car => car.selected)).reduce((r,{name,cars}) => (r[name]=cars.filter(ch => ch.selected).map(ch => ch.name),r), {}) Commented May 30, 2020 at 18:06

2 Answers 2

2

this snippet will help

 const array = [{
  "name":"John",
  "age":30,
  "cars": [
      { "selected":true,  "name":"Ford", "models": "Mustang"},
      { "selected":false, "name":"BMW", "models": "320" },
      { "selected":true, "name":"Fiat", "models":"500" }
  ]
 },
 {
  "name":"alex",
  "age":40,
  "cars": [
      { "selected":true,  "name":"tesla", "models": "x"},
      { "selected":false, "name":"merc", "models": "300" },
      { "selected":true, "name":"honda", "models":"accord" }
   ]
  }
]


const newArray = array.reduce((acc, rec) => {
  const cars = rec.cars.filter(c => c.selected)

  return cars.length ? {...acc, [rec.name]: cars.map(c => c.name)} : acc
}, {})

console.log(newArray)
Sign up to request clarification or add additional context in comments.

Comments

1

use forEach and build an object

Update: another solution using reduce

data = [
  {
    name: "John",
    age: 30,
    cars: [
      { selected: true, name: "Ford", models: "Mustang" },
      { selected: false, name: "BMW", models: "320" },
      { selected: true, name: "Fiat", models: "500" },
    ],
  },
  {
    name: "alex",
    age: 40,
    cars: [
      { selected: false, name: "tesla", models: "x" },
      { selected: false, name: "merc", models: "300" },
      { selected: false, name: "honda", models: "accord" },
    ],
  },
];


const output = data.reduce((acc, { name, cars }) => {
  const items = cars.filter(({selected}) => selected).map(({name}) => name);
  if (items.length > 0) {
     acc[name] = items;
  }
  return acc;
}, {});

console.log(output);

5 Comments

thanks for this. But my question was to acheive this using a reducer.
@Raji, sure, Updated the answer with using reduce. I thought using forEach will be simple here.
really appreciate for the update. All this works good but i do not want the empty record in final object. For Eg, In the above example for Alex if none of the cars have selected true then OUTPUT shouldn't have Alex record. I tried adding couple of conditions but then i am loosing the previous stored data. Can you help with that too please.
Updated answer to handle the case mentioned.
Appreciate your response. This is complete answer for me. So accepting it.

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.