Home > Net >  Insert new JSON objects in nested JS array based on condition
Insert new JSON objects in nested JS array based on condition

Time:04-06

For one of my e-commerce application requirement, I have a nested array of the form (Sample):

const data = [
    {
        "id": 1,
        "group": "upper-wear",
        "labels": [
            {
                "type": "shirts",
                "quantity": "20",
            },
        ],
        popular: true
    },
    {
        "id": 2,
        "group": "bottom-wear",
        "lables": [
            {
                "type": "trousers",
                "quantity": "31",
            },
        ],
        popular: true
    },
]

To this array, I need to insert new objects to the array 'labels' if the group value equals 'upper-wear'.

const newDataToInsert = [
    {
      "type": 'blazers',
      "quantity": 19
    },
  ]

This is what I tried so far, considering that for now I only need to insert to single label (i.e. 'upper-wear') (in future, there can be multiple labels category 'upper-wear', 'bottom-wear', to be inserted into):

const updatedArray = data.map((datum) => {
    if (datum.group === 'upper-wear') {
      return {
        ...datum,
        labels: [...datum.labels, ...newDataToInsert]
      };
    }
  });
  
  console.log(updatedArray);

But there seems to be a silly issue that I am missing as the result returns like this:

[
  {
    id: 1,
    group: 'upper-wear',
    labels: [ [Object], [Object] ],
    popular: true
  },
  undefined
]

I know there may be better approaches available, but this is what I can think of as the minimum solution for now.

any help to resolve the current or any better solution will be highly appreciated.

CodePudding user response:

Try with this

updatedArray = data.map((d) => {
    if (d.group && d.group === 'upper-wear') {
        return { ...d, labels: d.labels.concat(newDataToInsert) }
    } else {
        return d;
    }
})

const data = [
{
    "id": 1,
    "group": "upper-wear",
    "labels": [
        {
            "type": "shirts",
            "quantity": "20",
        },
    ],
    popular: true
},
{
    "id": 2,
    "group": "bottom-wear",
    "lables": [
        {
            "type": "trousers",
            "quantity": "31",
        },
    ],
    popular: true
},
];

const newDataToInsert = [
{
  "type": 'blazers',
  "quantity": 19
},
  ];

const updatedArray = data.map((d) => {
if (d.group && d.group === 'upper-wear') {
    return { ...d, labels: d.labels.concat(newDataToInsert) }
} else {
    return d;
}
});
  console.log(updatedArray)

Explaination

Here while mapping the data, we check for the condition

IF

  • If it matches then we will first copy the whole object from the variable b return { ...b }
  • after that we take another variable with the same name lables return { ...d, labels: d.labels.concat(newDataToInsert) },As per the JSON default nature the new variable with the same name will hold the latest value
  • Here in labels we first take a copy of old data and then merge it with newDataToInsert array labels: d.labels.concat(newDataToInsert), It will merge 2 arrays and store them in JSON with the name labels

Else

  • In else we just return the current values else { return d; }

CodePudding user response:

You don't actually need to iterate with map over the array. Just find an object in the array and change what you want.

const data=[{id:1,group:"upper-wear",labels:[{type:"shirts",quantity:"20"}],popular:true},{id:2,group:"bottom-wear",lables:[{type:"trousers",quantity:"31"}],popular:true}];
const newDataToInsert=[{type:"blazers",quantity:19}];

data.find(({ group }) => group === 'upper-wear')?.labels.push(...newDataToInsert);

console.log(data);
.as-console-wrapper { max-height: 100% !important; top: 0; }

CodePudding user response:

You're not returning all objects from your map. you're only returning a result when your criteria is met. This is resulting in your undefined objects...

const data = [
    { "id": 1, "group": "upper-wear", "labels": [ { "type": "shirts", "quantity": "20", }, ], popular: true },
    { "id": 2, "group": "bottom-wear", "lables": [ { "type": "trousers", "quantity": "31", }, ], popular: true },
]

const newDataToInsert = [ { "type": 'blazers',"quantity": 19 }, ]

const updatedArray = data.map(datum => { 
    if (datum.group === 'upper-wear') datum.labels = [...datum.labels,  ...newDataToInsert]
    return datum     
});
  
console.log(updatedArray);

CodePudding user response:

You can use Array#find to locate the desired group and then change labels for the group found. There are two options depending on how many items you would like to insert. Use Array#push to add the desired item; use forEach for more than one item:

const searchgroup = "upper-wear";
const target = data.find(({group}) => group === searchgroup);
target.labels.push(...newDataToInsert); //For one item to insert
//newDataToInsert.forEach(label => target.labels.push( label )); //For more than one item

const data = [{"id": 1, "group": "upper-wear", "labels": [{"type": "shirts", "quantity": "20"},],popular: true }, {"id": 2, "group": "bottom-wear", "lables": [{"type": "trousers", "quantity": "31", },],popular: true}];

const newDataToInsert = [{"type": 'blazers', "quantity": 19}];

//group to find
const searchgroup = "upper-wear";
//target element in data
const target = data.find(({group}) => group === searchgroup);
//check if group was found
if( target ) {
    //if there's only one product in newDataToInsert us this:
    //target.labels.push(...newDataToInsert);

    //if you have more than one product to be inserted use this; also works for one
    newDataToInsert.forEach(label => target.labels.push( label ));
} else {
    console.log( `No such group found: ${searchgroup}!` );
}

console.log( data );

  • Related