Reputation: 95
I have an array of strings:
["aa-q1-true", "bb-q1-false", "cc-q1-true", "aa-q2-true", "xx-q2-false", "yy-q2-true", "mm-q3-true", "mn-q3-false", "qr-q3-false"]
Where each string has a meaning. For example if we consider the first string i.e., "aa-q1-true"
Here the first part - aa
is the quiz answer, middle part - q1
is the question and true
, the last part is the answer status. Status can be true
or false
. This rule applies for each of the string inside the array.
Now I want to convert it into an array of objects like the following -
[
0: [{
quizAns: [{aa: true}, {bb: false}, {cc: true}]
quizQuestion: q1
}]
1: [{
quizAns: [{aa: true}, {xx: false}, {yy: true}]
quizQuestion: q2
}]
2: [{
quizAns: [{mm: true}, {mn: false}, {qr: false}]
quizQuestion: q3
}]
]
I just could not able to apprehend the logic to do this on my own. If you can just gimme some ideas or solution, it would be very helpful. Thank you so much for your time.
Upvotes: 0
Views: 52
Reputation: 2387
I am not a big fan of array.reduce
syntax cause of readability factor.
This loop will work, even if the input comes in a scrambled fashion.
const a = ["aa-q1-true", "bb-q1-false", "cc-q1-true", "aa-q2-true", "xx-q2-false", "yy-q2-true", "mm-q3-true", "mn-q3-false", "qr-q3-false"];let results = [];
const retObj = (que, ans) => {
const obj = {};
obj[`${que}`] = ans;
return obj;
};
for (let i in a){
let currEleArr = a[i].split("-");
let tarInd = parseInt(currEleArr[1].split("")[1]) - 1;
let que = currEleArr[0];
let ans= currEleArr[2];
if (!results[tarInd])
results[tarInd] = [{quizAns: []}];
if(!results[tarInd][0].quizQuestion)
results[tarInd][0]["quizQuestion"] = `q${tarInd + 1}`;
results[tarInd][0].quizAns.push(retObj(que, ans));
}
console.log(results);
Upvotes: 1
Reputation: 156
Just another approach with less code
const resultMap = array.reduce((acc, item) => {
// current data
const [answer, quizQuestion, status] = item.split("-");
// previous answers
const previousAnswers = acc[quizQuestion] ? acc[quizQuestion].quizAns : [];
// new answers
const newAnswers = [...previousAnswers, { [answer]: status }];
return { ...acc, [quizQuestion]: { quizQuestion, quizAns: newAnswers } };
}, {});
const result = Object.values(resultMap)
console.log(result)
Upvotes: 2
Reputation: 864
Just an another approach. Has less looping over the array than the other answer.
let questions = { };
let ans = ["aa-q1-true", "bb-q1-false", "cc-q1-true", "aa-q2-true", "xx-q2-false", "yy-q2-true", "mm-q3-true", "mn-q3-false", "qr-q3-false"]
.reduce((acc, curr) => {
let elements = curr.split("-");
let obj = {};
obj[elements[0]] = elements[2];
if (questions[elements[1]]) {
questions[elements[1]].push(obj);
} else {
questions[elements[1]]= [obj];
}
}, {})
let result = [];
for (let prop in questions) {
result.push({ "quizAns": questions[prop], "quizQuestion": prop });
}
console.log(result);
Upvotes: 1
Reputation: 64657
You would want to split each item by -
, and then you get the first and last item to get your answer object, and the middle to get which question it belongs to, then you just iteratively construct the solution:
let ans = ["aa-q1-true", "bb-q1-false", "cc-q1-true", "aa-q2-true", "xx-q2-false", "yy-q2-true", "mm-q3-true", "mn-q3-false", "qr-q3-false"].map((s) => s.split('-')).reduce((carry, current) => {
let existingIndex = carry.findIndex((item) => item.quizQuestion === current[1]);
if (existingIndex === -1) {
carry.push({quizAns: [], quizQuestion: current[1]});
existingIndex = carry.length - 1;
}
carry[existingIndex].quizAns.push({[current[0]]: current[2]});
return carry;
}, []);
console.log(ans);
Upvotes: 3