Home > Software engineering >  Need to filter an JavaScript object
Need to filter an JavaScript object

Time:05-12

I need to filter an JS object as below format. I have some array of Object. every object contain title and data. I need to filter the object. title will not repet in object it will make an array of data and store every data in that. Object

 let results = [
            {
                "title": "exam",
                "data": {
                    "status": "Active",
                    "studentId": "44",
                    "universityId": "0",
                    "mediaId": "12",
                    "mediaName": "massey university",
                    "mediaSrc": "https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg",
                    "mediaDownload": 4
                }
            },
            {
                "title": "prospectus",
                "data": {
                    "status": "Active",
                    "studentId": "44",
                    "universityId": "0",
                    "mediaId": "12",
                    "mediaName": "massey university",
                    "mediaSrc": "https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg",
                    "mediaDownload": 4
                }
            },
            {
                "title": "prospectus",
                "data": {
                    "status": "Active",
                    "studentId": "44",
                    "universityId": "23",
                    "mediaId": "12",
                    "mediaName": "massey university",
                    "mediaSrc": "https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg",
                    "mediaDownload": 4
                }
            },]

Filter object will be like this. title will not be repeated it will make an array.

 "results": [
            {
                "title": "exam",
                "data": {
                    "status": "Active",
                    "studentId": "44",
                    "universityId": "0",
                    "mediaId": "12",
                    "mediaName": "massey university",
                    "mediaSrc": "https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg",
                    "mediaDownload": 4
                }
            },
            {
                "title": "prospectus",
                "data": [{
                    "status": "Active",
                    "studentId": "44",
                    "universityId": "0",
                    "mediaId": "12",
                    "mediaName": "massey university",
                    "mediaSrc": "https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg",
                    "mediaDownload": 4
                },
                {
                    "status": "Active",
                    "studentId": "44",
                    "universityId": "23",
                    "mediaId": "12",
                    "mediaName": "massey university",
                    "mediaSrc": "https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg",
                    "mediaDownload": 4
                }]

I have tried this.

let filterData = [];
mainData.data.results.map((value) => {
  if (filterData.length == 0) {
    let obj = {
      title: "title",
      data: [{ ...value.data }],
    };
    filterData.push(obj);
  } else {
    let found = false;
  }
});

CodePudding user response:

This isn't really a filter operation, more of a reduce job where you want to collect data for the same title.

For that, I'd recommend creating a map of title to data

// this is just your data structure minified
const results = [{"title":"exam","data":{"status":"Active","studentId":"44","universityId":"0","mediaId":"12","mediaName":"massey university","mediaSrc":"https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg","mediaDownload":4}},{"title":"prospectus","data":{"status":"Active","studentId":"44","universityId":"0","mediaId":"12","mediaName":"massey university","mediaSrc":"https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg","mediaDownload":4}},{"title":"prospectus","data":{"status":"Active","studentId":"44","universityId":"23","mediaId":"12","mediaName":"massey university","mediaSrc":"https://unisearch-static-contents.s3.ap-southeast-1.amazonaws.com/ADMIN/massey university-9a2b9a22-b648-4ef1-a806-97bb0da9b337.jpg","mediaDownload":4}}];

// Collect data by title
const collect = results.reduce(
  (map, { title, data }) => ({
    ...map,
    [title]: [...(map[title] ?? []), data],
  }),
  {}
);

// Convert the mapped object to an array of objects
// with `title` and `data` properties
const filterData = Object.entries(collect).map(([title, data]) => ({
  title,
  data,
}));

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

This will always put data in an array which keeps your data-structure consistent. If you really want single-element arrays to be destructured, use this instead for the last part

const filterData = Object.entries(collect).map(([title, data]) => ({
  title,
  data: data.length === 1 ? data[0] : data,
}));

CodePudding user response:

The main problem here is to remember which title already exists and reduce it to just one with the data of all the same titles.

The above solution is good but it has a complexity of O(n^2) because it performs two loops. One to reduce the elements into an array of { title: [datas]} objects and one to transform it into the desired output of the form [{title, datas},...].

Using this solution we can perform the process with a complexity of O(n), using a hash table (directory) structure to remember the titles and reduce only those that are repeated.

let filterData = []
let directory = {}
mainData.data.results.map( (obj) => {
     if(directory[obj.title] === undefined) {
     directory[obj.title] = filterData.length
     filterData.push({title: obj.title, data: [obj.data] })
   } else {
     filterData[directory[obj.title]].data.push(obj.data)
   }
})

CodePudding user response:

var resultObj = {}

results.forEach((item)=>{
    if(!resultObj[item.title]){
        resultObj[item.title] = {
            title:item.title,
            data:[]
        }
    }
    resultObj[item.title].data.push(item.data)
})

var finalResultList = Object.values(resultObj)

console.log(finalResultList)

  • Related