storagemode11
storagemode11

Reputation: 895

Map object if property is found in another array of objects

This is my case.

data: [
    {
      q: "question 1",
      a: "answer 1"
    }, 
    {
      q: "question 2"
    }
]

How can I map this into key: value pair so that the final output is { "question 1": "answer 1"}?

The trick is that only if a property exists then it should be assigned to the new object as above example { "question N": "answer N"}.

I have tried combining .map() and .filter(), but it didn't work.

For example:

const obj = data.map(e => e.q).filter(s => s.a)

Thanks.

Upvotes: 7

Views: 2387

Answers (6)

onetyone
onetyone

Reputation: 562

Here you go:

const obj = data.filter(s => s.a).map(e => ({[e.q]: e.a}))

Upvotes: -1

Andrew
Andrew

Reputation: 776

Here's what I believe you're trying to do, and this will account for multiple questions as well.

First, you need to use filter to get rid of anything that doesn't have the a property defined.

Then, you can use a reducer function.

This reducer accumulates a brand new object (starting with {} which is passed as the 2nd argument to reduce). It assigns each property (question name) to each value (answer) and returns the new accumulated variable, until it's done iterating.

const data = [{q: "question 1", a: "answer 1"}, {q: "question 2"}, {q: "question 3", a: "answer 3"}]

const obj = data.filter(item => item.hasOwnProperty('a'))
    .reduce(function(acc, cur) {
        acc[cur.q] = cur.a
        return acc 
    }, {})

Upvotes: 1

MiDas
MiDas

Reputation: 374

Using the reduce method effectively ensure u run a single loop with a conditional inside, instead of a map and a filter like the previous answers which are both definitely correct as well

let data = [{q: "question 1",a: "answer 1"},{q: "question 2"}]

const obj = data.reduce((acc,cur) => {
If(cur.a && cur.q) {
acc.push({[`${cur.q}`]: cur.a})
}. 
return acc
} ,[])

console.log(obj)

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386736

For a single object, you could take Object.fromEntries for creating a sigle object out of key/value pairs.

var data = [{ q: "question 1", a: "answer 1" }, { q: "question 2" }],
    result = Object.fromEntries(data
        .map(({ q, a }) => [q, a])
        .filter(([_, a]) => a)
    );

console.log(result);

Upvotes: 2

Code Maniac
Code Maniac

Reputation: 37755

You need to filter element first and then map

let data = [{q: "question 1",a: "answer 1"},{q: "question 2"}]

const obj = data.filter(s => s.a)
                .map(({q,a}) => ({ [q]: a }))

console.log(obj)


Can we get output as object, you can use reduce and build an Object,

let data = [{q: "question 1",a: "answer 1"},{q: "question 2"}]

const obj = data.reduce((op,{q,a})=>{
  if( a ) op[q] = a
  return op
},{})

console.log(obj)


In modern browser you can Object.fromEntries too

let data = [{q: "question 1",a: "answer 1"},{q: "question 2"}]

const obj = Object.fromEntries(data.filter(s => s.a)
                .map(({q,a}) => [q,a]))

console.log(obj)

Upvotes: 8

Nikhil
Nikhil

Reputation: 6641

You can use map() and then filter().

let data = [{ q: "question 1", a: "answer 1" }, { q: "question 2" } ];

let result = data.map(item => {
  if (item.q && item.a) {
    return {
      [item.q]: item.a
    };
  }
}).filter(item => item); // Filter undefined values.

console.log(result);

Upvotes: 4

Related Questions