Tengo dos matrices keyVals y rows definidas a continuación:

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

He escrito el siguiente código para generar un 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);

Los valores de Res son los siguientes:

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

Quiero modificar function dArray(rows, keyVals) de modo que Res excluya todos los valores vacíos como se muestra a continuación:

Res = 
[
  {
    "Hostname": "ABC",
    "Check1kStatus": "PASS",
    "Check2Status": "PASS",
    "Check3Status": "FAIL",
    "Check3ErrorHeading": "Heading3",
    "Check3ErrorDetail": "ErrorDetails3"
  }
]
0
meallhour 24 jun. 2020 a las 19:46

5 respuestas

La mejor respuesta
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;
}
1
lightBullet 24 jun. 2020 a las 17:12
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
luek baja 24 jun. 2020 a las 17:02

Antes de devolver la respuesta, use map y Object.entries para filtrar valores vacíos en el objeto.

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));
0
sivako 24 jun. 2020 a las 17:22

Esto lo hace filtrando el resultado de su llamada Object.values().

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"
    }
  ];
}
0
Cat 24 jun. 2020 a las 17:42

Puede hacerlo con una función especial filterObject.

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 está adaptado del filtro polimórfico de mi biblioteca de programación funcional, rubico. Documentos para el filtro aquí, si está interesado.

1
richytong 24 jun. 2020 a las 16:59