1

I have a questions object with nested objects:

const questions = {
  QID5: {
    choices: {
      1: { choiceText: "Label 1" },
      2: { choiceText: "Label 2" },
      3: { choiceText: "Label 3" }
    }
  },
  QID6: {
    choices: {
      1: { choiceText: "English" },
      2: { choiceText: "French" }
    }
  }
};

And an array of responses:

const responses = [
  {
    labels: {
      QID5: ["Label 1", "Label 3"],
      QID6: ["English", "French"]
    }
  },
  {
    labels: {
      QID5: ["Label 1"],
      QID6: ["English"]
    }
  },
  {
    labels: {
      QID5: ["Label 2", "Label 3"],
      QID6: ["English"]
    }
  }
];

I want to count the occurrence of each choice in questions in each of the responses for a particular question (QID) and put them in arrays as a property (x, y) of a new object

For example the desired result for QID5 should be:

const desiredResult = {
  id: "QID5",
  x: ["Label 1", "Label 2", "Label 3"],
  y: [2, 1, 2]
};

Label 1 in desiredResult.x gets the value 2 in desiredResult.y (because it appears in two of the responses) and so on...

How can I achieve this result?

Here is what I've tried:


function getResults(id) {
  return responses.flatMap(response => response.labels[id])

}

const arr = getResults("QID5");
const counts = {};
arr.forEach((x) => {
  counts[x] = (counts[x] || 0) + 1;
});

const x = Object.keys(counts)
const y = Object.values(counts)

console.log(x)
console.log(y)
2
  • Hi @SevenSouls mention what you have tried. Will give you suggestion what to do or how you can correct it Commented Aug 31, 2022 at 23:36
  • Added what I've tried Commented Aug 31, 2022 at 23:40

2 Answers 2

1

You can get the x values by mapping the question choices into the choiceText values. You can then get each y value by iterating the x values, counting whether the value occurs in the labels for the question id in each response:

const questions = {
  QID5: {
    choices: {
      1: { choiceText: "Label 1" },
      2: { choiceText: "Label 2" },
      3: { choiceText: "Label 3" }
    }
  },
  QID6: {
    choices: {
      1: { choiceText: "English" },
      2: { choiceText: "French" }
    }
  }
};

const responses = [
  {
    labels: {
      QID5: ["Label 1", "Label 3"],
      QID6: ["English", "French"]
    }
  },
  {
    labels: {
//      QID5: ["Label 1"],
      QID6: ["English"]
    }
  },
  {
    labels: {
      QID5: ["Label 2", "Label 3"],
      QID6: ["English"]
    }
  }
];

const getResults = (id) => {
  const x = Object.values(questions[id].choices).map(({ choiceText }) => choiceText);
  const y = x.map(l => responses.reduce((acc, r) => acc + (r.labels[id]?.includes(l) || 0), 0))
  return { id, x, y }
}

console.log(getResults('QID5'))

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you! What if some ID does not exist in responses, but does exist in questions. Currently adding optional chaining r.labels[id]?.includes(l) returns null in the y. Is there a way to account for that?
@SevenSouls just use (r.labels[id]?.includes(l) || 0). See my edit.
1

Here's a simpler solution if you have to sort the labels by label number:

const responses = [
  {
    labels: {
      QID5: ["Label 1", "Label 3"],
      QID6: ["English", "French"]
    }
  },
  {
    labels: {
      QID5: ["Label 1"],
      QID6: ["English"]
    }
  },
  {
    labels: {
      QID5: ["Label 2", "Label 3"],
      QID6: ["English"]
    }
  }
];

function getResults(id) {
  return responses.flatMap(response => response.labels[id])

}

const arr = getResults("QID5");
const counts = {};
arr.forEach((x) => {
  counts[x] = (counts[x] || 0) + 1;
});

// sort the kays by the lable number, which is the 6th character in the key (would vary if the key is changed)
const x = Object.keys(counts).sort((key, nextKey) => parseInt(key[6], 10) - parseInt(nextKey[6], 10));
const y = x.map(key => counts[key]) // get each key's corresponding number

const desiredObject = {
    id: "QID5", // or an variable / function arg
  x,
  y
}

console.log(desiredObject)

Comments

Your Answer

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.