Zichen Ma
Zichen Ma

Reputation: 987

Can I use javascript map, filter.. to map two arrays has same id?

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!

Upvotes: 1

Views: 1234

Answers (4)

Jonas Wilms
Jonas Wilms

Reputation: 138267

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()];

Upvotes: 3

Patrick Roberts
Patrick Roberts

Reputation: 51886

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);

Upvotes: 0

Nina Scholz
Nina Scholz

Reputation: 386600

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; }

Upvotes: 0

Ghoul Ahmed
Ghoul Ahmed

Reputation: 4806

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);

Upvotes: 0

Related Questions