0

The below code will have input as array of objects and I would like to convert into a different format.

The below code works fine but I need a more refactored shorter format of what I am trying to achieve.

var res =  {"matchObject":"{\"data\":[{\"id\":\"jack1\",\"firstname\":\"jack\",\"lastname\":\"hudson\",\"dob\":\"1990-01-01T00:00:00.000Z\",\"email\":\"jack1@yahoo.com\",\"phone\":null,\"orgid\":\"001\"},{\"id\":\"jack2\",\"firstname\":\"Jack\",\"lastname\":\"Clinton\",\"dob\":\"1991-01-01T00:00:00.000Z\",\"email\":\"jack.clinton@yahoo.com\",\"phone\":\"+16464922600\",\"orgid\":\"002\"}]}"};
var parsedObj = JSON.parse(res.matchObject);

var res = [];
for(var key in parsedObj.data){
    var emailObj = {};
    var phoneObj = {}
    if(parsedObj.data[key].email !== null){
        emailObj.matchedRes = parsedObj.data[key].email;
        emailObj.id = parsedObj.data[key].id;
        emailObj.type = "email";
        res.push(emailObj);
    }
    if(parsedObj.data[key].phone !== null){
        phoneObj.matchedRes = parsedObj.data[key].phone;
        phoneObj.id = parsedObj.data[key].id;
        phoneObj.type="phone";
        res.push(phoneObj);
    }  
}
console.log(res);

Desired output:

[ { matchedRes: 'jack1@yahoo.com', id: 'jack1', type: 'email' },
  { matchedRes: 'jack.clinton@yahoo.com', id: 'jack2', type: 'email' },
  { matchedRes: '+16464922600', id: 'jack2', type: 'phone' } ]

In the above code separate objects are created with phone and email for same id.

Rafa Romero
  • 2,667
  • 5
  • 25
  • 51
user804401
  • 1,990
  • 9
  • 38
  • 71

4 Answers4

3

Here is a solution!

I just did a generic reducer, and then I use it on phone and email.

Then, I just spread the result of both calls to the result array :)

var res =  {"matchObject":"{\"data\":[{\"id\":\"jack1\",\"firstname\":\"jack\",\"lastname\":\"hudson\",\"dob\":\"1990-01-01T00:00:00.000Z\",\"email\":\"jack1@yahoo.com\",\"phone\":null,\"orgid\":\"001\"},{\"id\":\"jack2\",\"firstname\":\"Jack\",\"lastname\":\"Clinton\",\"dob\":\"1991-01-01T00:00:00.000Z\",\"email\":\"jack.clinton@yahoo.com\",\"phone\":\"+16464922600\",\"orgid\":\"002\"}]}"};
var parsedObj = JSON.parse(res.matchObject);

const extractData = (obj, type) => obj.reduce((acc, elt) => (
  elt[type] && acc.push({matchedRes: elt[type], id: elt.id, type: type})
, acc),[]);

const result = [...extractData(parsedObj.data, 'email'), ...extractData(parsedObj.data, 'phone')];

console.log(result);

Hope this helps, please do not hesitate to comment if you have any question ;)

sjahan
  • 5,720
  • 3
  • 19
  • 42
  • Best not to abuse the conditional operator as a replacement for `if`. The conditional operator is when you need a resulting *expression* - if you don't need an expression, the conditional operator is not appropriate – CertainPerformance Feb 14 '19 at 08:47
  • I agree with you, it is often less readable and only appropriate in some cases. But as OP asked for a shorter format... :) I gave my best to the shortest version! – sjahan Feb 14 '19 at 08:49
  • You can destructuring assignment to make it even shorted https://stackoverflow.com/questions/54605286/what-is-destructuring-assignment-and-what-are-its-uses/54605288#54605288 – Code Maniac Feb 14 '19 at 08:56
  • Thanks you for the overwhelming response. Learned lot of refactoring techniques with Reduce today. – user804401 Feb 14 '19 at 09:13
  • @user804401 You should google something like `javascript performance map vs reduce`, but from my understanding, this will be quite the same. The performance will mainly depends on your mapping/reducing function, but in the end, both functions do the same: iterating on an array, executing the function to map/reduce, then adding the result of this function in a target object. Maybe reduce is slightly heavier (not even sure about that), but I think that when you come to that kind of fine tuning issue, you will probably want to modify your data model more than using something else than `reduce`! – sjahan Feb 19 '19 at 09:43
2

You can use reduce with destructuring assignment . and check if email or phone is there than add a object accordingly

var res =  {"matchObject":"{\"data\":[{\"id\":\"jack1\",\"firstname\":\"jack\",\"lastname\":\"hudson\",\"dob\":\"1990-01-01T00:00:00.000Z\",\"email\":\"jack1@yahoo.com\",\"phone\":null,\"orgid\":\"001\"},{\"id\":\"jack2\",\"firstname\":\"Jack\",\"lastname\":\"Clinton\",\"dob\":\"1991-01-01T00:00:00.000Z\",\"email\":\"jack.clinton@yahoo.com\",\"phone\":\"+16464922600\",\"orgid\":\"002\"}]}"};
var parsedObj = JSON.parse(res.matchObject);

let op = parsedObj.data.reduce((out,{id,email,phone})=>{
  if(email){
    out.push({matchedRes:email,id,type:`email`})
  } 
  if(phone){
  out.push({matchesRes:phone,id,type:`phone`})
  }
  return out
},[])

console.log(op)

If you want to see more use cases of You can destructuring assignment and it's uses you can check this one out

Code Maniac
  • 37,143
  • 5
  • 39
  • 60
  • Read here https://hackernoon.com/javascript-performance-test-for-vs-for-each-vs-map-reduce-filter-find-32c1113f19d7 – Code Maniac Feb 18 '19 at 16:15
2

This should be possible with reduce:

var res =  {"matchObject":"{\"data\":[{\"id\":\"jack1\",\"firstname\":\"jack\",\"lastname\":\"hudson\",\"dob\":\"1990-01-01T00:00:00.000Z\",\"email\":\"jack1@yahoo.com\",\"phone\":null,\"orgid\":\"001\"},{\"id\":\"jack2\",\"firstname\":\"Jack\",\"lastname\":\"Clinton\",\"dob\":\"1991-01-01T00:00:00.000Z\",\"email\":\"jack.clinton@yahoo.com\",\"phone\":\"+16464922600\",\"orgid\":\"002\"}]}"};
var parsedObj = JSON.parse(res.matchObject);
const keyFields = ["email", "phone"];

let result = parsedObj.data.reduce((acc, val) => {
    keyFields.forEach(k => {
       if (val[k]) acc.push({ matchedRes: val.email, id: val.id,  type: k});
    });
    return acc;
}, []);

console.log("Result: ", result);
Terry Lennox
  • 29,471
  • 5
  • 28
  • 40
2

If you are looking for a little shorter code but still easy to read for anybody:

var res =  {"matchObject":"{\"data\":[{\"id\":\"jack1\",\"firstname\":\"jack\",\"lastname\":\"hudson\",\"dob\":\"1990-01-01T00:00:00.000Z\",\"email\":\"jack1@yahoo.com\",\"phone\":null,\"orgid\":\"001\"},{\"id\":\"jack2\",\"firstname\":\"Jack\",\"lastname\":\"Clinton\",\"dob\":\"1991-01-01T00:00:00.000Z\",\"email\":\"jack.clinton@yahoo.com\",\"phone\":\"+16464922600\",\"orgid\":\"002\"}]}"};
var parsedObj = JSON.parse(res.matchObject);

var res = [];

Object.entries(parsedObj.data).forEach(el => {
    el = el[1]
    if(el.email !== null)
      res.push({
        matchedRes: el.email,
        id: el.id,
        type: "email"
      })
    if(el.phone !== null)
       res.push({
        matchedRes: el.phone,
        id: el.id,
        type: "phone"
    })
})

console.log(res);
Silvio Biasiol
  • 856
  • 8
  • 14