Convert strConflictedYesReviewers data into a single object which is grouped by ownerid and then groupby opportunityid

Convert strConflictedYesReviewers data into a single object which is grouped by ownerid first and then groupby opportunityid which contains array of response.

I get a dynamic string(strConflictedYesReviewers) which contains multiple user recordswhere each record is separated by semicolon and then each record represents ownerid and opportunityid separated by asterisk.

const strConflictedYesReviewers = "88639280*198719943;88642547*198721749;88627345*198721749;88664734*198721749;88686221*198721749;88676217*198721749;88664734*198721749;88686221*198721749;88676217*198721749;"
.split(";")
.map(item => item.split("*"))     
.filter(item => !!item[0])
.map(item => ({ownerid: item[0], opportunityid: item[1]}))
.reduce(function(acc, curr) {
  (acc[curr["ownerid"]] = acc[curr["ownerid"]] || []).push(curr["opportunityid"]);
  return acc;
}, {});
   

console.log(strConflictedYesReviewers);
//need the object like the foloowing in the end.
{
  "68642547": {
    "222": [
      "Yes"
    ]
  },
  "88627345": {
    "111": [
      "No",
      "Yes",
      "No"
    ],
    "222": [
      "Yes"
    ]
  },
  "88642547": {
    "111": [
      "Yes",
      "No"
    ],
    "222": [
      "Yes",
      "No"
    ]
  }
}
1 Like

I assume the 111 and 222 stuff is suppose to be the opportunity ids for that owner id? What is the Yes and No part?

1 Like

Yes and No are the multiple responses for a specific ownerid under the same opportunityid.
e.g
88627345 responded 3 times for opportunityid(111) and responded 1 time for opportunityid(222) in the following case:

"88627345": {
    "111": [
      "No",
      "Yes",
      "No"
    ],
    "222": [
      "Yes"
    ]
  },
1 Like

The original string is:

const strConflictedYesReviewers = "88639280*198719943;88642547*198721749;88627345*198721749;88664734*198721749;88686221*198721749;88676217*198721749;88664734*198721749;88686221*198721749;88676217*198721749;";

The codes extracted from there are:

const reviewerCodesList = strConflictedYesReviewers.split(";")
.map(item => item.split("*"))     
.filter(item => !!item[0]);
[ 
  ['88639280', '198719943'],
  ['88642547', '198721749'],
  ['88627345', '198721749'],
  ['88664734', '198721749'],
  ['88686221', '198721749'],
  ['88676217', '198721749'],
  ['88664734', '198721749'],
  ['88686221', '198721749'],
  ['88676217', '198721749']
]

That’s converted to an object with:

const reviewerCodesObj = reviewerCodesList.map(item => ({ownerid: item[0], opportunityid: item[1]}));
[ 
  {ownerid: '88639280', opportunityid: '198719943'},
  {ownerid: '88642547', opportunityid: '198721749'},
  {ownerid: '88627345', opportunityid: '198721749'},
  {ownerid: '88664734', opportunityid: '198721749'},
  {ownerid: '88686221', opportunityid: '198721749'},
  {ownerid: '88676217', opportunityid: '198721749'},
  {ownerid: '88664734', opportunityid: '198721749'},
  {ownerid: '88686221', opportunityid: '198721749'},
  {ownerid: '88676217', opportunityid: '198721749'}
]

And lastly, those are combined by unique owners, with:

const conflictedYesReviewers = reviewerCodesObj.reduce(function(acc, curr) {
  (acc[curr["ownerid"]] = acc[curr["ownerid"]] || []).push(curr["opportunityid"]);
  return acc;
}, {});
[
  {88627345: ['198721749']},
  {88639280: ['198719943']},
  {88642547: ['198721749']},
  {88664734: ['198721749', '198721749']},
  {88676217: ['198721749', '198721749']},
  {88686221: ['198721749', '198721749']}
]

You are wanting to add yes and no information to those quoted id numbers, so let’s add an array to each of those id numbers.

const conflictedYesReviewers = reviewerCodesObj.reduce(function(acc, curr) {
  acc[curr.ownerid] = acc[curr.ownerid] || [];
  const yesNoObj = {};
  yesNoObj[curr.opportunityid] = ["yes, no"];
  acc[curr.ownerid].push(yesNoObj);
  return acc;
}, {});

That now gives the following structure:

[
  {88627345: [
    {198721749: ["yes, no"]}
  ]},
  {88639280: [
    {198719943: ["yes, no"]}
  ]},
  {88642547: [
    {198721749: ["yes, no"]}
  ]},
  {88664734: [
    {198721749: ["yes, no"]},
    {198721749: ["yes, no"]}
  ]},
  {88676217: [
    {198721749: ["yes, no"]},
    {198721749: ["yes, no"]}
  ]},
  {88686221: [
    {198721749: ["yes, no"]},
    {198721749: ["yes, no"]}
  ]}
]

The updated code in total is:

const strConflictedYesReviewers = "88639280*198719943;88642547*198721749;88627345*198721749;88664734*198721749;88686221*198721749;88676217*198721749;88664734*198721749;88686221*198721749;88676217*198721749;";
const reviewerCodesList = strConflictedYesReviewers.split(";")
.map(item => item.split("*"))     
.filter(item => !!item[0]);
const reviewerCodesObj = reviewerCodesList.map(item => ({ownerid: item[0], opportunityid: item[1]}));
const conflictedYesReviewers = reviewerCodesObj.reduce(function(acc, curr) {
  acc[curr.ownerid] = acc[curr.ownerid] || [];
  const yesNoObj = {};
  yesNoObj[curr.opportunityid] = ["yes", "no"];
  acc[curr.ownerid].push(yesNoObj);
  return acc;
}, {});
console.log(conflictedYesReviewers);

The next thing to figure out from here, is:

  • is that structure the kind of thing that you are wanting, and
  • where is the information about yes and no choices being obtained from?
2 Likes

Hey Paul,
I apologise, I made a mistake. I copied the incorrect strConflictedYesReviewers at the top.
The correct one is the following:

68642547*222*Yes;88627345*111*No;88627345*111*Yes;88627345*111*No;88627345*222*Yes;88642547*111*Yes;88642547*111*No;88642547*222*Yes;88642547*222*No; **strong text**
2 Likes

Thank you.

The reviewerCodesList variable looks to have good information:

[
  ['68642547', '222', 'Yes'],
  ['88627345', '111', 'No'],
  ['88627345', '111', 'Yes'],
  ['88627345', '111', 'No'],
  ['88627345', '222', 'Yes'],
  ['88642547', '111', 'Yes'],
  ['88642547', '111', 'No'],
  ['88642547', '222', 'Yes'],
  ['88642547', '222', 'No']
]

Turning that into an object looks to be nice an easy, by using a response keyword for yes or no.

const reviewerCodesObj = reviewerCodesList.map(item => ({ownerid: item[0], opportunityid: item[1], response: item[2]}));
[
  {ownerid: '68642547', opportunityid: '222', response: 'Yes'},
  {ownerid: '88627345', opportunityid: '111', response: 'No'},
  {ownerid: '88627345', opportunityid: '111', response: 'Yes'},
  {ownerid: '88627345', opportunityid: '111', response: 'No'},
  {ownerid: '88627345', opportunityid: '222', response: 'Yes'},
  {ownerid: '88642547', opportunityid: '111', response: 'Yes'},
  {ownerid: '88642547', opportunityid: '111', response: 'No'},
  {ownerid: '88642547', opportunityid: '222', response: 'Yes'},
  {ownerid: '88642547', opportunityid: '222', response: 'No'}
]

And adding yes/no from there is just a simple update when compiling the results:

const conflictedYesReviewers = reviewerCodesObj.reduce(function(acc, curr) {
  acc[curr.ownerid] = acc[curr.ownerid] || [];
  acc[curr.ownerid][curr.opportunityid] = acc[curr.ownerid][curr.opportunityid] || [];
  acc[curr.ownerid][curr.opportunityid].push(curr.response);
  return acc;
}, {});
{
  {"68642547":[
    {"222":["Yes"]}
  ]},
  {"88627345":[
    {"111":["No"], ["Yes"], ["No"]},
    {"222":["Yes"]}
  ]},
  {"88642547":[
    {"111":["Yes"], ["No"]},
    {"222":["Yes"], ["No"]}
  ]}
}

The code in full is:

const strConflictedYesReviewers = "68642547*222*Yes;88627345*111*No;88627345*111*Yes;88627345*111*No;88627345*222*Yes;88642547*111*Yes;88642547*111*No;88642547*222*Yes;88642547*222*No;";
const reviewerCodesList = strConflictedYesReviewers.split(";")
  .map(item => item.split("*"))     
  .filter(item => !!item[0]);
const reviewerCodesObj = reviewerCodesList.map(item => ({ownerid: item[0], opportunityid: item[1], response: item[2]}));
const conflictedYesReviewers = reviewerCodesObj.reduce(function(acc, curr) {
  acc[curr.ownerid] = acc[curr.ownerid] || [];
  acc[curr.ownerid][curr.opportunityid] = acc[curr.ownerid][curr.opportunityid] || [];
  acc[curr.ownerid][curr.opportunityid].push(curr.response);
  return acc;
}, {});
console.log(conflictedYesReviewers);
2 Likes

Hey Paul,
Txs for the reply but this is not the structure I want.

First of all I want an object at the end, that object will have properties(ownerid) and each property(ownerid) will have another object which will have properties(opportunityid) and each property(opportunityid) will have an array of resaponses(Yes, no values)

Short explanation of the above case e.g is:.

"88627345": {
    "111": [
      "No",
      "Yes",
      "No"
    ],
    "222": [
      "Yes"
    ]
  }


Final object at the end should look like this:
{
  "68642547": {
    "222": [
      "Yes"
    ]
  },
  "88627345": {
    "111": [
      "No",
      "Yes",
      "No"
    ],
    "222": [
      "Yes"
    ]
  },
  "88642547": {
    "111": [
      "Yes",
      "No"
    ],
    "222": [
      "Yes",
      "No"
    ]
  }
}
1 Like

Please check the code, and let me know how the end result differs from what you require.

1 Like

Hey Paul,
Txs for the reply. The end result differs from what I required. Please look at the console in the attached pic.

1 Like

that would have to be || {} to generate the output requested (an object of objects containing arrays)

2 Likes

Very good. So by using this updated code, we are closer to your desired end result.

const strConflictedYesReviewers = "68642547*222*Yes;88627345*111*No;88627345*111*Yes;88627345*111*No;88627345*222*Yes;88642547*111*Yes;88642547*111*No;88642547*222*Yes;88642547*222*No;";
const reviewerCodesList = strConflictedYesReviewers.split(";")
  .map(item => item.split("*"))     
  .filter(item => !!item[0]);
const reviewerCodesObj = reviewerCodesList.map(item => ({ownerid: item[0], opportunityid: item[1], response: item[2]}));
const conflictedYesReviewers = reviewerCodesObj.reduce(function(acc, curr) {
  acc[curr.ownerid] = acc[curr.ownerid] || {};
  acc[curr.ownerid][curr.opportunityid] = acc[curr.ownerid][curr.opportunityid] || [];
  acc[curr.ownerid][curr.opportunityid].push(curr.response);
  return acc;
}, {});
console.log(conflictedYesReviewers);
2 Likes

Hey Paul,
Txs for the reply. It works now. Really Appreciated.

1 Like