0

I have two arrays keyVals and rows defined as below:

    keyVals = 
    [
      "Status",
      "ErrorHeading",
      "ErrorDetail"
    ]
    
rows =
[
  {
    "Hostname": "ABC",
    "name": "Check1",
    "Status": "PASS",
    "ErrorHeading": "",
    "ErrorDetail": ""
  },
  {
    "Hostname": "ABC",
    "name": "Check2",
    "Status": "PASS",
    "ErrorHeading": "",
    "ErrorDetail": ""
  },
  {
    "Hostname": "ABC",
    "name": "Check3",
    "Status": "FAIL",
    "ErrorHeading": "Heading3",
    "ErrorDetail": "ErrorDetails3"
  }
]

I have written the following code to generate a Res:

function dArray(rows, keyVals) {
    const response = Object.values(rows.reduce((res, {Hostname, name, ...o}) => {
        res[Hostname] = res[Hostname] || {Hostname};
        keyVals.forEach(kv => res[Hostname][name + kv] = o[kv]);
        return res;
    }, {}));
    return response;
}

const Res = dArray(rows, keyVals);

The Res values looks as below:

Res = 
[
  {
    "Hostname": "ABC",
    "Check1kStatus": "PASS",
    "Check1ErrorHeading": "",
    "Check1ErrorDetail": "",
    "Check2Status": "PASS",
    "Check2ErrorHeading": "",
    "Check2ErrorDetail": "",
    "Check3Status": "FAIL",
    "Check3ErrorHeading": "Heading3",
    "Check3ErrorDetail": "ErrorDetails3"
  }
]

I want to modify function dArray(rows, keyVals) such that the Res excludes all empty values as below:

Res = 
[
  {
    "Hostname": "ABC",
    "Check1kStatus": "PASS",
    "Check2Status": "PASS",
    "Check3Status": "FAIL",
    "Check3ErrorHeading": "Heading3",
    "Check3ErrorDetail": "ErrorDetails3"
  }
]
3
  • There's no such thing as a "JSON Object" Commented Jun 24, 2020 at 16:48
  • keyVals and rows are arrays Commented Jun 24, 2020 at 16:48
  • And the problem is? if (o[kv]) { ... } Commented Jun 24, 2020 at 16:51

5 Answers 5

1
function dArray(rows, keyVals) {
    const response = Object.values(rows.reduce((res, {Hostname, name, ...o}) => {
        res[Hostname] = res[Hostname] || {Hostname};
        keyVals.forEach(kv => (o[kv] && (res[Hostname][name + kv] = o[kv])));
        return res;
    }, {}));
    return response;
}
Sign up to request clarification or add additional context in comments.

Comments

1

You can do it with a special filterObject function.

const keyVals = ["Status", "ErrorHeading", "ErrorDetail"]
    
const rows = [
  { "Hostname": "ABC", "name": "Check1", "Status": "PASS", "ErrorHeading": "", "ErrorDetail": "" },
  { "Hostname": "ABC", "name": "Check2", "Status": "PASS", "ErrorHeading": "", "ErrorDetail": "" },
  { "Hostname": "ABC", "name": "Check3", "Status": "FAIL", "ErrorHeading": "Heading3", "ErrorDetail": "ErrorDetails3" },
]

const filterObject = (fn, x) => {
  const y = {}
  for (const k in x) {
    const ok = fn(x[k])
    if (ok) { y[k] = x[k] }
  }
  return y
}

function dArray(rows, keyVals) {
    const response = Object.values(rows.reduce((res, {Hostname, name, ...o}) => {
        res[Hostname] = res[Hostname] || {Hostname};
        keyVals.forEach(kv => res[Hostname][name + kv] = o[kv]);
        return res;
    }, {}));
    return response.map(obj => filterObject(x => x !== '', obj))
}

const Res = dArray(rows, keyVals);

console.log(Res)

filterObject is adapted from the polymorphic filter from my functional programming library, rubico. Docs for filter here, if you are interested.

Comments

1
function dArray(rows, keyVals) {
  const response = Object.values(rows.reduce((res, {Hostname, name}) => {
      res[Hostname] = res[Hostname] || {Hostname};
      keyVals.forEach(kv => res[Hostname][name + kv] = o[kv]);
      return res;
  }, {}));

  let keys=Object.keys(response[0]);
  for(let i=0,l=keys.length;i<l;i++){
    if(!response[0][keys[i]]){
      delete response[0][keys[i]];
    }  
  }

  return response;
}

1 Comment

Is there a way I can update function dArray(rows, keyVals) instead of creating another function?
0

Before returning response, use map and Object.entries to filter empty values in object.

function dArray(rows, keyVals) {
  const response = Object.values(
    rows.reduce((res, { Hostname, name, ...o }) => {
      res[Hostname] = res[Hostname] || { Hostname };
      keyVals.forEach((kv) => (res[Hostname][name + kv] = o[kv]));
      return res;
    }, {})
  );
  return response.map((obj) =>
    Object.fromEntries(Object.entries(obj).filter(([, val]) => val))
  );
}

keyVals = ["Status", "ErrorHeading", "ErrorDetail"];

rows = [
  {
    Hostname: "ABC",
    name: "Check1",
    Status: "PASS",
    ErrorHeading: "",
    ErrorDetail: "",
  },
  {
    Hostname: "ABC",
    name: "Check2",
    Status: "PASS",
    ErrorHeading: "",
    ErrorDetail: "",
  },
  {
    Hostname: "ABC",
    name: "Check3",
    Status: "FAIL",
    ErrorHeading: "Heading3",
    ErrorDetail: "ErrorDetails3",
  },
];

console.log(dArray(rows, keyVals));

Comments

0

This does it by filtering the output of your Object.values() call.

const
  keyVals = [ "Status", "ErrorHeading", "ErrorDetail" ],
  rows = getRows();

function dArray(rows, keyVals) {
  const reducedValues = Object.values(
    rows.reduce( (res, { Hostname, name, ...o }) => {
      res[Hostname] = res[Hostname] || { Hostname };
      keyVals.forEach(kv => res[Hostname][name + kv] = o[kv]);
      return res;
    }, {})
  ),
  response = [
    Object.fromEntries(
      Object.entries(reducedValues[0]).filter(en=>en[1])
    )
  ];
  return response;
}
const Res = dArray(rows, keyVals);
console.log(Res);


function getRows(){
  return [{
      "Hostname": "ABC",
      "name": "Check1",
      "Status": "PASS",
      "ErrorHeading": "",
      "ErrorDetail": ""
    },
    {
      "Hostname": "ABC",
      "name": "Check2",
      "Status": "PASS",
      "ErrorHeading": "",
      "ErrorDetail": ""
    },
    {
      "Hostname": "ABC",
      "name": "Check3",
      "Status": "FAIL",
      "ErrorHeading": "Heading3",
      "ErrorDetail": "ErrorDetails3"
    }
  ];
}

Comments

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.