Dev365
Dev365

Reputation: 57

Creating a new array of objects by finding values in JSON data

Not sure I can do this but what I'm trying to do is create a new array by searching through some JSON data to find a key and taking the whole object into the new array if the key is found. Below is a sample of the data I am using.

{
  "students": {
    "AB10001": {
      "campus": "cda",
      "subjects": ["history", "english"],
    }
    "AB10002": {
      "campus": "asd",
      "subjects": ["maths"],
    }
    "AB10003": {
      "campus": "asd",
      "subjects": ["english"],
    }
    "AB10004": {
      "campus": "asd",
      "subjects": ["history"],
    }
    "AB10005": {
      "campus": "cda",
      "subjects": ["maths", "science"],
    }
    "AB10006": {
      "campus": "asd",
      "subjects": ["science"],
    }
    "AB10007": {
      "campus": "cda",
      "subjects": ["science"],
    }
    "AB10008": {
      "campus": "asd",
      "subjects": ["science", "history"],
    }
    "AB10009": {
      "campus": "cda",
      "subjects": ["history"],
    }
    "AB10010": {
      "campus": "cda",
      "subjects": ["history", "maths"],
    }
  }
}

So what I want to do is search through the students key of subjects for all students who do history and then create another array from that, taking the whole student, while leaving the original object the same.

So I want to end up with something that like this:

{
  "historyStudents": {
    "AB10001": {
      "campus": "cda",
      "subjects": ["history", "english"],
    }
    "AB10004": {
      "campus": "asd",
      "subjects": ["history"],
    }
    "AB10008": {
      "campus": "asd",
      "subjects": ["science", "history"],
    }
    "AB10009": {
      "campus": "cda",
      "subjects": ["history"],
    }
    "AB10010": {
      "campus": "cda",
      "subjects": ["history", "maths"],
    }
  }
}

Any insights or assistance would be very helpful. Thanks in advance!

Upvotes: 2

Views: 457

Answers (4)

Nenad Vracar
Nenad Vracar

Reputation: 122027

You can use Object.keys() and reduce() to create new object with only students with history subject.

var data = {"students":{"AB10001":{"campus":"cda","subjects":["history","english"]},"AB10002":{"campus":"asd","subjects":["maths"]},"AB10003":{"campus":"asd","subjects":["english"]},"AB10004":{"campus":"asd","subjects":["history"]},"AB10005":{"campus":"cda","subjects":["maths","science"]},"AB10006":{"campus":"asd","subjects":["science"]},"AB10007":{"campus":"cda","subjects":["science"]},"AB10008":{"campus":"asd","subjects":["science","history"]},"AB10009":{"campus":"cda","subjects":["history"]},"AB10010":{"campus":"cda","subjects":["history","maths"]}}}

var result = {
 historyStudents: Object.keys(data.students)
  .reduce(function(r, e) {
    if(data.students[e].subjects.includes('history')) r[e] = data.students[e]
    return r;
   }, {})
 }

console.log(result)

Upvotes: 2

cнŝdk
cнŝdk

Reputation: 32145

You need just to loop over the data.students keys using Object.keys() and for each one check if the relative object value has history in its subjetcs array:

var result = {
  "historyStudents": {}
};

Object.keys(data.students).forEach(function(k) {
  if (data.students[k].subjects.indexOf("history") > -1) {
    result.historyStudents[k] = data.students[k];
  }
});

Demo:

var data = {
  "students": {
    "AB10001": {
      "campus": "cda",
      "subjects": ["history", "english"],
    },
    "AB10002": {
      "campus": "asd",
      "subjects": ["maths"],
    },
    "AB10003": {
      "campus": "asd",
      "subjects": ["english"],
    },
    "AB10004": {
      "campus": "asd",
      "subjects": ["history"],
    },
    "AB10005": {
      "campus": "cda",
      "subjects": ["maths", "science"],
    },
    "AB10006": {
      "campus": "asd",
      "subjects": ["science"],
    },
    "AB10007": {
      "campus": "cda",
      "subjects": ["science"],
    },
    "AB10008": {
      "campus": "asd",
      "subjects": ["science", "history"],
    },
    "AB10009": {
      "campus": "cda",
      "subjects": ["history"],
    },
    "AB10010": {
      "campus": "cda",
      "subjects": ["history", "maths"],
    }
  }
};
var result = {
  "historyStudents": {}
};

Object.keys(data.students).forEach(function(k) {
  if (data.students[k].subjects.indexOf("history") > -1) {
    result.historyStudents[k] = data.students[k];
  }
});
console.log(result);

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386520

You could get the keys, filter it and build a new object out of the key and the values. Then use Object.assign for creating a single object.

function getStudents(object, subject) {
    return Object.assign({}, ...Object
        .keys(object)
        .filter(k => object[k].subjects.includes(subject))
         .map(k => ({ [k]: object[k] }))
    );
}


var object = { students: { AB10001: { campus: "cda", subjects: ["history", "english"] }, AB10002: { campus: "asd", subjects: ["maths"] }, AB10003: { campus: "asd", subjects: ["english"] }, AB10004: { campus: "asd", subjects: ["history"] }, AB10005: { campus: "cda", subjects: ["maths", "science"] }, AB10006: { campus: "asd", subjects: ["science"] }, AB10007: { campus: "cda", subjects: ["science"] }, AB10008: { campus: "asd", subjects: ["science", "history"] }, AB10009: { campus: "cda", subjects: ["history"] }, AB10010: { campus: "cda", subjects: ["history", "maths"] } } },
    result = { historyStudents: getStudents(object.students, 'history') };

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

Upvotes: 0

vs1682
vs1682

Reputation: 555

In addition to above answers you can also es6 destructuring to get the desired result

const  data = {"students":{"AB10001":{"campus":"cda","subjects":["history","english"]},"AB10002":{"campus":"asd","subjects":["maths"]},"AB10003":{"campus":"asd","subjects":["english"]},"AB10004":{"campus":"asd","subjects":["history"]},"AB10005":{"campus":"cda","subjects":["maths","science"]},"AB10006":{"campus":"asd","subjects":["science"]},"AB10007":{"campus":"cda","subjects":["science"]},"AB10008":{"campus":"asd","subjects":["science","history"]},"AB10009":{"campus":"cda","subjects":["history"]},"AB10010":{"campus":"cda","subjects":["history","maths"]}}}

const historyStudents = {};
for(const stdId in data.students) {

  // es6 destructuring
  const { subjects } = data.students[stdId];

  if(subjects.includes('history')){
    historyStudents[stdId] = data.students[stdId]; 
  }
}
// object property shorthand
console.log({ historyStudents });

Upvotes: 0

Related Questions