1

I have two arrays: one questions another is answers. I want to add answers array which has the same questionID into questions array answers attribute like this:

const questions = {
    total: 18,
    page: 1,
    questions: [{
        firstName: 'testing',
        lastName: '001',
        citizenType: 'VERIFIED CITIZEN',
        imageUrl: 'https://source.unsplash.com/400x400/',
        question: '546435645364564356',
        createdAt: 1563486386916,
        id: '905aa4c9-38b8-4429-a91b-56e819ea53e9',
        answers : []
    }, {
        firstName: 'testing',
        lastName: '001',
        citizenType: 'VERIFIED CITIZEN',
        imageUrl: 'https://source.unsplash.com/400x400/',
        question: 'questions',
        createdAt: 1563484856214,
        id: '69165abc-3327-4d99-856a-290042863247',
        answers : []
    }, {
        firstName: 'testing',
        lastName: '001',
        citizenType: 'VERIFIED CITIZEN',
        imageUrl: 'https://source.unsplash.com/400x400/',
        question: 'ffff',
        createdAt: 1563475882538,
        id: '97a1d4a1-7e6d-4859-93ee-5591918bba87',
        answers : []
    }]
};
  const answers = [
    {
        citizenType: 'VERIFIED CITIZEN',
        createdAt: 1563486386916,
        firstName: 'Dan',
        questionID: '905aa4c9-38b8-4429-a91b-56e819ea53e9',
        id: '905aa4c9-38b8-4429-a91b-56e819ea53e1',
        imageUrl: 'https://source.unsplash.com/400x400/',
        lastName: 'Jone',
        answer: 'answer from Dan Joe',
    },
    {
        citizenType: 'VERIFIED CITIZEN',
        createdAt: 1563486386916,
        firstName: 'Bill',
        questionID: '69165abc-3327-4d99-856a-290042863247',
        id: '905aa4c9-38b8-4429-a91b-56e819ea53e2',
        imageUrl: 'https://source.unsplash.com/400x400/',
        lastName: 'Li',
        answer: 'answer from Bill',
    },
    {
        citizenType: 'VERIFIED CITIZEN',
        createdAt: 1563486386916,
        firstName: 'Steve',
        questionID: '97a1d4a1-7e6d-4859-93ee-5591918bba87',
        id: '905aa4c9-38b8-4429-a91b-56e819ea53e3',
        imageUrl: 'https://source.unsplash.com/400x400/',
        lastName: 'Sun',
        answer: 'answer from Steve',
    },
    {
        citizenType: 'VERIFIED CITIZEN',
        createdAt: 1563486386916,
        firstName: 'Steve',
        questionID: '111111111',
        id: '905aa4c9-38b8-4429-a91b-56e819ea53e3',
        imageUrl: 'https://source.unsplash.com/400x400/',
        lastName: 'Sun',
        answer: 'answer from MissMatch',
    },
];

let questionArr = questions.questions;
let answerArr = questionArr[0].answers;

// can use I use map, filter or other pure functions to achieve this?
questionArr.forEach(q => {
    answers.forEach(a => {
        if (q.id === a.questionID) {
            q.answers.push(a);
        }
    })
})

console.log(questions);

right now the result (questions) is what I want, but just wondering if I can achieve this with some ES6 pure functions, like map filter... Thank you so much!

4 Answers 4

3

If you really want to iterate both arrays (thats O(n * m) time complexity), you could build up a new array:

 const result = questions.map(question => ({
    ...question,
   answers: answers.filter(it => it.questionID === question.id), 
 }));

But I'd rather build up a Map from the questions, then its O(n + m):

 const questionByID = new Map(questions.map(q => ([q.id, { ...q, answers: [] }])));

 for(const answer of answers)
   questionByID.get(answer.questionID).answers.push(answer);

 const result = [...questionByID.values()];
Sign up to request clarification or add additional context in comments.

2 Comments

Not sure why the object spread is necessary since each q already has an empty answers array. Also wouldn't this be a good candidate for Object.fromEntries() since the id is a string?
hi @Jonas, thank you for the solutions. I only able to get O(m * n) answer, but never thought Map(). Very nice solution.
0

try this:

const questions = { total: 18, page: 1, questions: [{ firstName: 'testing', lastName: '001', citizenType: 'VERIFIED CITIZEN', imageUrl: 'https://source.unsplash.com/400x400/', question: '546435645364564356', createdAt: 1563486386916, id: '905aa4c9-38b8-4429-a91b-56e819ea53e9', answers : [] }, { firstName: 'testing', lastName: '001', citizenType: 'VERIFIED CITIZEN', imageUrl: 'https://source.unsplash.com/400x400/', question: 'questions', createdAt: 1563484856214, id: '69165abc-3327-4d99-856a-290042863247', answers : [] }, { firstName: 'testing', lastName: '001', citizenType: 'VERIFIED CITIZEN', imageUrl: 'https://source.unsplash.com/400x400/', question: 'ffff', createdAt: 1563475882538, id: '97a1d4a1-7e6d-4859-93ee-5591918bba87', answers : [] }] };
const answers = [ { citizenType: 'VERIFIED CITIZEN', createdAt: 1563486386916, firstName: 'Dan', questionID: '905aa4c9-38b8-4429-a91b-56e819ea53e9', id: '905aa4c9-38b8-4429-a91b-56e819ea53e1', imageUrl: 'https://source.unsplash.com/400x400/', lastName: 'Jone', answer: 'answer from Dan Joe', }, { citizenType: 'VERIFIED CITIZEN', createdAt: 1563486386916, firstName: 'Bill', questionID: '69165abc-3327-4d99-856a-290042863247', id: '905aa4c9-38b8-4429-a91b-56e819ea53e2', imageUrl: 'https://source.unsplash.com/400x400/', lastName: 'Li', answer: 'answer from Bill', }, { citizenType: 'VERIFIED CITIZEN', createdAt: 1563486386916, firstName: 'Steve', questionID: '97a1d4a1-7e6d-4859-93ee-5591918bba87', id: '905aa4c9-38b8-4429-a91b-56e819ea53e3', imageUrl: 'https://source.unsplash.com/400x400/', lastName: 'Sun', answer: 'answer from Steve', }, { citizenType: 'VERIFIED CITIZEN', createdAt: 1563486386916, firstName: 'Steve', questionID: '111111111', id: '905aa4c9-38b8-4429-a91b-56e819ea53e3', imageUrl: 'https://source.unsplash.com/400x400/', lastName: 'Sun', answer: 'answer from MissMatch', }, ];

questions.questions.map(res=> Object.assign(res,{answers:answers.filter(ele=>ele.questionID === res.id)}))

console.log(questions);

1 Comment

Hi @Ghoul Ahmed, thank you! It works! Thank you so much!
0

You could store the target arrays in a map and push the answers.

var questions = { total: 18, page: 1, questions: [{ firstName: 'testing', lastName: '001', citizenType: 'VERIFIED CITIZEN', imageUrl: 'https://source.unsplash.com/400x400/', question: '546435645364564356', createdAt: 1563486386916, id: '905aa4c9-38b8-4429-a91b-56e819ea53e9', answers: [] }, { firstName: 'testing', lastName: '001', citizenType: 'VERIFIED CITIZEN', imageUrl: 'https://source.unsplash.com/400x400/', question: 'questions', createdAt: 1563484856214, id: '69165abc-3327-4d99-856a-290042863247', answers: [] }, { firstName: 'testing', lastName: '001', citizenType: 'VERIFIED CITIZEN', imageUrl: 'https://source.unsplash.com/400x400/', question: 'ffff', createdAt: 1563475882538, id: '97a1d4a1-7e6d-4859-93ee-5591918bba87', answers: [] }] },
    answers = [{ citizenType: 'VERIFIED CITIZEN', createdAt: 1563486386916, firstName: 'Dan', questionID: '905aa4c9-38b8-4429-a91b-56e819ea53e9', id: '905aa4c9-38b8-4429-a91b-56e819ea53e1', imageUrl: 'https://source.unsplash.com/400x400/', lastName: 'Jone', answer: 'answer from Dan Joe' }, { citizenType: 'VERIFIED CITIZEN', createdAt: 1563486386916, firstName: 'Bill', questionID: '69165abc-3327-4d99-856a-290042863247', id: '905aa4c9-38b8-4429-a91b-56e819ea53e2', imageUrl: 'https://source.unsplash.com/400x400/', lastName: 'Li', answer: 'answer from Bill' }, { citizenType: 'VERIFIED CITIZEN', createdAt: 1563486386916, firstName: 'Steve', questionID: '97a1d4a1-7e6d-4859-93ee-5591918bba87', id: '905aa4c9-38b8-4429-a91b-56e819ea53e3', imageUrl: 'https://source.unsplash.com/400x400/', lastName: 'Sun', answer: 'answer from Steve' }, { citizenType: 'VERIFIED CITIZEN', createdAt: 1563486386916, firstName: 'Steve', questionID: '111111111', id: '905aa4c9-38b8-4429-a91b-56e819ea53e3', imageUrl: 'https://source.unsplash.com/400x400/', lastName: 'Sun', answer: 'answer from MissMatch' }];
    targets = new Map(questions.questions.map(o => [o.id, o.answers]));

answers.forEach(o => targets.has(o.questionID) && targets.get(o.questionID).push(o));

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

2 Comments

const targets = Object.fromEntries(questionArr.map(o => [o.id, o.answers])); answerArr.forEach(o => targets[o.id].push(o)); also works
@Nina, thank you for the solution! Pretty much similar to upper one. Nice!
0

Analogous to the suggested solution using Map, you can use a plain object in a much similar way, constructing it with Object.fromEntries():

const questionsObject = Object.fromEntries(questions.map(q => [q.id, q]));

answers.forEach(answer => {
  questionsObject[answer.questionID].answers.push(answer);
});

const result = Object.values(questionsObject);

1 Comment

Hi Patrick, first of all, thank you! I agree that using Map() is better

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.