5
\$\begingroup\$

I have an app with a bunch of questions defined in a yaml file. For various reasons I would like the data to be divided into sections (section_0, section_1, section_2 etc.). When I load this file into my js app I get an object that looks like this:

const questionData = {
 "section_0": {
 "items": [
 {
 "key": "0.0",
 "title": "Question one",
 "type": "integer"
 },
 {
 "key": "0.1",
 "title": "Question 0.1",
 "type": "integer"
 }
 ]
 },
 "section_1": {
 "items": [
 {
 "key": "1.0",
 "title": "Some title",
 "type": "integer",
 "options": {
 "1": "one",
 "2": "two",
 "3": "other option"
 }
 },
 {
 "key": "1.1",
 "title": "Question 1.1",
 "description": "Longer description text",
 "type": "string"
 },
 {
 "key": "1.2",
 "title": "Question 1.2",
 "type": "integer",
 "options": {
 "0": "option zero",
 "1": "option one",
 "2": "option two"
 }
 },
 {
 "key": "1.3",
 "title": "Q 1.2",
 "type": "boolean",
 "options": {
 "true": "Yes",
 "false": "No"
 }
 },
 {
 "key": "1.4",
 "title": "Question 1.4",
 "type": "string"
 },
 {
 "key": "1.5",
 "title": "Question 1.5",
 "type": "integer"
 },
 {
 "key": "1.6",
 "title": "Question 1.6",
 "type": "integer"
 },
 {
 "key": "1.7",
 "title": "Q1.7",
 "type": "integer"
 }
 ]
 }
}

(a lot more questions and sections in the actual app)

Now I would like to be able to query for a question by the key. I found/figured out two ways to do this. One is sort of home made and the other flattens the array using lodash.

Traversing the object:

function findByKey(data, key){
 if (data.hasOwnProperty('key') && data['key'] === key) {
 return data;
 }
 for (let i = 0; i < Object.keys(data).length; i++) {
 if (typeof data[Object.keys(data)[i]] === 'object') {
 let obj = findByKey(data[Object.keys(data)[i]], key);
 if (obj != null) {
 return obj;
 }
 }
 }
 return null;
}
findByKey(questionData, "0.1")
// => returns the object with the key "0.1"

Using lodash to create a flat array of objects:

const questionsArray = _.flatten(_.map(_.keys(questionData), function(val) {
 return questionData[val].items;
}));
_.find(questionsArray, function(obj) { return obj.key === "0.1" })
// => returns the object with the key "0.1"

Do I need to transform the questionData object like this just to be able to query for an object somewhere in the tree or am I missing some simpler solution (other than not creating the nested structure in the first place)?

asked Oct 11, 2016 at 7:56
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

I usually have methods to normalize data in the format I want it so you don't have to iterate again. If you want you can have Schema that provides you methods or access to the data using custom methods.

var questions = new QuestionsSchema(data); // Normalizes to preferred format questions.getOriginal(); // => Access to the original object 
questions.getQuestion('0.1'); // => {"key": "0.0","title": "Question one","type": "integer"}
questions.getSection('section_1'); // => whole section

I like more the composed functions you build, is a more like functional way.

answered Oct 12, 2016 at 14:41
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.