0

I have an array of objects and I would like to get it into a format used by react-csv (2D array). The 2D should look like a nested loop, something like

Image of data in spreadsheet program

and the end result should be like

[
  ["Name", "Message", "Column", "configDataType","dbDataType"],
  ["STAGE", "Columns present in source config but not in the database.", "TEST"],
  ["", "", "TEST1"],
  ["", "", "TEST2"],
  ["", "Columns present in database but not in the source config.", ""],
  ["", "Columns with datatype mismatch.", "LAST_NAME", "varchar(50)", "varchar(40)"],
  ["", "", "FIRST_NAME", "varchar(50)", "varchar(40)"],
  ["RAW", "Column sets are identical."],
  ["LAST", "Column sets are identical."],
  ["HIST", "Column sets are identical."],
  ["CORE", "Column sets are identical."],
  ["ADDR", "Column sets are identical."],
  ["CONFIG", "Column sets are identical."],
  ["ACTION", "Column sets are identical."],
]

This is what I have done so far, but I am not able to get the intended result. Please advise me on what I am missing.

const data = {
  "STAGE": [{
      "infoLevel": "error",
      "message": "Columns present in source config but not in the database.",
      "columns": [],
      "columnsName": [
        "TEST",
        "TEST1",
        "TEST2"
      ],
      "type": "String"
    },
    {
      "infoLevel": "error",
      "message": "Columns present in database but not in the source config.",
      "columns": [],
      "columnsName": [],
      "type": "String"
    },
    {
      "infoLevel": "error",
      "message": "Columns with datatype mismatch.",
      "columns": [{
        "name": "LAST_NAME",
        "configDatatype": "varchar(50)",
        "dbDatatype": "varchar(40)"
      }, {
        "name": "FIRST_NAME",
        "configDatatype": "varchar(50)",
        "dbDatatype": "varchar(40)"
      }],
      "columnsName": [],
      "type": "Table"
    }
  ],
  "RAW": [{
    "infoLevel": "success",
    "message": "Column sets are identical.",
    "columns": [],
    "columnsName": [],
    "type": "String"
  }],
  "LAST": [{
    "infoLevel": "success",
    "message": "Column sets are identical.",
    "columns": [],
    "columnsName": [],
    "type": "String"
  }],
  "HIST": [{
    "infoLevel": "success",
    "message": "Column sets are identical.",
    "columns": [],
    "columnsName": [],
    "type": "String"
  }],
  "CORE": [{
    "infoLevel": "success",
    "message": "Column sets are identical.",
    "columns": [],
    "columnsName": [],
    "type": "String"
  }],
  "ADDR": [{
    "infoLevel": "success",
    "message": "Column sets are identical.",
    "columns": [],
    "columnsName": [],
    "type": "String"
  }],
  "TRAN": [{
    "infoLevel": "success",
    "message": "Column sets are identical.",
    "columns": [],
    "columnsName": [],
    "type": "String"
  }],
  "CONFIG": [{
    "infoLevel": "success",
    "message": "Column sets are identical.",
    "columns": [],
    "columnsName": [],
    "type": "String"
  }],
  "ACTION": [{
    "infoLevel": "success",
    "message": "Column sets are identical.",
    "columns": [],
    "columnsName": [],
    "type": "String"
  }]
}

const res = _.flattenDeep(Object.keys(data).map(i => {
  return data[i].map(j => {
    return {
      ...j,
      tableName: i
    }
  })
}))

console.log(res.map(i => {
  return [
    i.tableName,
    i.message,
    ...((i.columns.length > 0 ? i.columns : i.columnsName).map(j => typeof j === 'string' ? j : j.name)),
    ..._.compact(((i.columns.length > 0 ? i.columns : i.columnsName).map(j => typeof j === 'string' ? '' : j.configDatatype))),
    ...(((i.columns.length > 0 ? i.columns : i.columnsName).map(j => typeof j === 'string' ? '' : j.dbDatatype)))
  ]
}))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js"></script>

2
  • TEST1 and TEST2 are not in the data. Instead, Arun and Abnc are. You may want to amend either your expected result, or your data. Commented Nov 3, 2021 at 16:52
  • @HereticMonkey Amended the data. Sorry about that. Commented Nov 3, 2021 at 16:57

1 Answer 1

1

Why not to use old style imperative code? Try this:

const data = {
  "STAGE": [{
      "infoLevel": "error",
      "message": "Columns present in source config but not in the database.",
      "columns": [],
      "columnsName": [
        "TEST",
        "Arun",
        "Abnc"
      ],
      "type": "String"
    },
    {
      "infoLevel": "error",
      "message": "Columns present in database but not in the source config.",
      "columns": [],
      "columnsName": [],
      "type": "String"
    },
    {
      "infoLevel": "error",
      "message": "Columns with datatype mismatch.",
      "columns": [{
        "name": "LAST_NAME",
        "configDatatype": "varchar(50)",
        "dbDatatype": "varchar(40)"
      }, {
        "name": "FIRST_NAME",
        "configDatatype": "varchar(50)",
        "dbDatatype": "varchar(40)"
      }],
      "columnsName": [],
      "type": "Table"
    }
  ],
  "RAW": [{
    "infoLevel": "success",
    "message": "Column sets are identical.",
    "columns": [],
    "columnsName": [],
    "type": "String"
  }],
  "LAST": [{
    "infoLevel": "success",
    "message": "Column sets are identical.",
    "columns": [],
    "columnsName": [],
    "type": "String"
  }],
  "HIST": [{
    "infoLevel": "success",
    "message": "Column sets are identical.",
    "columns": [],
    "columnsName": [],
    "type": "String"
  }],
  "CORE": [{
    "infoLevel": "success",
    "message": "Column sets are identical.",
    "columns": [],
    "columnsName": [],
    "type": "String"
  }],
  "ADDR": [{
    "infoLevel": "success",
    "message": "Column sets are identical.",
    "columns": [],
    "columnsName": [],
    "type": "String"
  }],
  "TRAN": [{
    "infoLevel": "success",
    "message": "Column sets are identical.",
    "columns": [],
    "columnsName": [],
    "type": "String"
  }],
  "CONFIG": [{
    "infoLevel": "success",
    "message": "Column sets are identical.",
    "columns": [],
    "columnsName": [],
    "type": "String"
  }],
  "ACTION": [{
    "infoLevel": "success",
    "message": "Column sets are identical.",
    "columns": [],
    "columnsName": [],
    "type": "String"
  }]
};

var rows = [];
for (var c1 in data) {
  const list = data[c1];
  for (var i in list) {
    const obj = list[i];
    var c2 = obj.message;
    for (var j in obj.columnsName) {
      rows.push([c1, c2, obj.columnsName[j]]);
      c1 = ""; c2 = "";
    }
    for (var j in obj.columns) {
      const col = obj.columns[j];
      rows.push([c1, c2, col.name, col.configDatatype, col.dbDatatype]);
      c1 = ""; c2 = "";
    }
    if (c2 != "") rows.push([c1, c2]);
    c1 = "";
  }
}

console.log(rows);

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks a lot. I get a lot of eslint errors for for..in. Trying to fix those
You can replace the 3 for...in which use the i and j vars with classic for i=0;i<array.length;i++ while for the outermost loop you can use Object.keys to retrieve the c1 values.

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.