简体   繁体   中英

How to map over an array and use index such that empty values are eliminated?

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

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.

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

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM