Home > front end >  Filter array by comparing property values
Filter array by comparing property values

Time:09-26

Ok i have an array as following

const services = [
   {
      "data":[
         {
            "duration":{
               "start":"10",
               "end":"11"
            },
            "serviceId":215
         },
         {
            "duration":{
               "start":"4",
               "end":"5"
            },
            "serviceId":37
         },
         
      ],
      "title":"1632767400000"
   },
   {
      "data":[
         {
            "duration":{
               "start":"9",
               "end":"11"
            },
            "serviceId":215
         },
         {
            "duration":{
               "start":"2",
               "end":"3"
            },
            "serviceId":37
         },
         
      ],
      "title":"1632767400000"
   },
]

As you can see i have anoth array (data) inside my main array which has multiple objects.

i want to filter these data, for example i want to get data which has start and end duration inbetween 9 and 11.

So my final output of the filtered data must be as follows

  const services = [
       {
          "data":[
             {
                "duration":{
                   "start":"10",
                   "end":"11"
                },
                "serviceId":215
             },
           
          ],
          "title":"1632767400000"
       },
       {
          "data":[
             {
                "duration":{
                   "start":"9",
                   "end":"11"
                },
                "serviceId":215
             },
            
             
          ],
          "title":"1632767400000"
       },
    ]

I have tried something like the following

 const test = services.map((item) => {
      return item.data.filter((service) => {
        return (
          parseInt(service.duration.start) >=
            9 &&
          parseInt(service.duration.end) <=
            11
        );
      });
    });

But it only returns the data elements array and not the full array like i need. How do i filter data arrays in my main array and keep the original structure of the main array.

FYI: any lodash solutions are welcome too.

CodePudding user response:

services is an array of objects, so first you have to map over the array and return an object will all properties as ...o and data with filtered objects whose duration.start <= 11

services.map((o) => ({
  ...o,
  data: o.data.filter(
    (obj) =>  obj.duration.start >= 9 &&  obj.duration.end <= 11
  ),
}));

const services = [
  {
    data: [
      {
        duration: {
          start: "10",
          end: "11",
        },
        serviceId: 215,
      },
      {
        duration: {
          start: "4",
          end: "5",
        },
        serviceId: 37,
      },
    ],
    title: "1632767400000",
  },
  {
    data: [
      {
        duration: {
          start: "9",
          end: "11",
        },
        serviceId: 215,
      },
      {
        duration: {
          start: "2",
          end: "3",
        },
        serviceId: 37,
      },
    ],
    title: "1632767400000",
  },
];

const result = services.map((o) => {
  return {
    ...o,
    data: o.data.filter((obj) =>  obj.duration.start >= 9 &&  obj.duration.end <= 11),
  };
});

console.log(result);

CodePudding user response:

Your response data is dealing only with the data node in the services array.

Debugging your map function

services.map((item) => {
  return item.data.filter((service) => {
    return (
      parseInt(service.duration.start) >=
        9 &&
      parseInt(service.duration.end) <=
        11
    );
  });
});

Your map function loops through services array. On looping the array it filters the data node and check the condition and returns the data nodes which satisfies that condition. Please Note it reurns only the data nodes

You have to send not just the data nodes, it should use the all the nodes in each objects of services array. This can be done using spread operator like {data, ...restNodes}. Here the each object from services array will be splitted into two set. The data node from each object of will be available in the variable called data and rest all variables will be available in restNodes variable.

So in map, return the filter action on the data node aswell as the restNodes variable. So this will give all the data in each nodes from services array and filtered data from data node.

const services = [
    {
        "data": [
            { "duration": { "start": "10", "end": "11" }, "serviceId": 215 },
            { "duration": { "start": "4", "end": "5" }, "serviceId": 37 },

        ],
        "title": "1632767400000"
    },
    {
        "data": [
            { "duration": { "start": "9", "end": "11" }, "serviceId": 215 },
            { "duration": { "start": "2", "end": "3" }, "serviceId": 37 },

        ],
        "title": "1632767400000"
    },
];
const output = services.map(({data, ...restNodes}) => {
    return {
        data: data.filter((service) => {
            return (
                parseInt(service.duration.start) >=
                9 &&
                parseInt(service.duration.end) <=
                11
            );
        }),
        ...restNodes,
    };
});
console.log(output);

  • Related