Skip to content

Instantly share code, notes, and snippets.

@lewdev
Created May 2, 2024 01:13
Show Gist options
  • Save lewdev/bc01bc38891f7526e681bbf4e751da5a to your computer and use it in GitHub Desktop.
Save lewdev/bc01bc38891f7526e681bbf4e751da5a to your computer and use it in GitHub Desktop.
πŸ‘¨β€πŸ’» Small CSV Parse & Generate Library

Small Library

I was looking into CSV methods on StackOverflow which didn't have great answers. So I put together some solutions that I'd appreciate.

Here's an answer I made for "JavaScript array to CSV," which didn't have any solid answers.

I found a great solution for parsing CSV so I figured that my work is complete by including a great parseCSV solution I found a while ago by Trevor Dixon.

// Inspired by: https://stackoverflow.com/a/64618766/1675237 & https://stackoverflow.com/a/58034688/1675237
const arrToCsv = arr => arr.map(row => row.map(s => (
  String(s).match(/,|"/) ? `"${s.replace(/"/g,'""')}"` : s
)).join`,`).join`\n`;

const arrObjToCsv = objArr => {
  if (!Array.isArray(objArr) || objArr.length === 0) return "";
  const headers = Object.keys(objArr[0]);
  return arrToCsv([
    headers,
    ...objArr.map(obj => headers.map(key => obj[key]))
  ]);
};

// Source: https://stackoverflow.com/a/14991797/1675237
const parseCSV = s => {
  arr = [];
  q = 0;
  for (let row = 0, col = 0, c = 0; c < s.length; c++) {
    let cc = s[c], nc = s[c+1];
    arr[row] = arr[row] || [];
    arr[row][col] = arr[row][col] || '';
    if (cc == '"' && q&& nc == '"') { arr[row][col] += cc; ++c; continue; }
    if (cc == '"') { q= !q; continue; }
    if (cc == ',' && !q) { ++col; continue; }
    if (cc == '\r' && nc == '\n' && !q) { ++row; col = 0; ++c; continue; }
    if (cc == '\n' && !q) { ++row; col = 0; continue; }
    if (cc == '\r' && !q) { ++row; col = 0; continue; }
    arr[row][col] += cc;
  }
  return arr;
};

console.log(arrToCsv([
  ["name1", 2, 3],
  ["name2", 4, 5],
  ["name3", 6, 7],
  ["name4", 8, 9],
  ["name5", 10, 11]
]));

console.log(arrObjToCsv([
  { name: "name1", age: 22, count: 3 },
  { name: "name2", age: 23, count: 4 },
  { name: "name3", age: 24, count: 5 },
  { name: "name4", age: 25, count: 6 },
  { name: "name5", age: 26, count: 7 }
]));
<title>πŸ‘¨β€πŸ’» Small CSV Parse & Generate Library Demo</title>
<h1>πŸ‘¨β€πŸ’» Small CSV Parse & Generate Library Demo</h1>
<pre id=o></pre>
<script>
const arrToCsv = arr => arr.map(row => row.map(s => (
String(s).match(/,|"/) ? `"${s.replace(/"/g,'""')}"` : s
)).join`,`).join`\n`;
const arrObjToCsv = objArr => {
if (!Array.isArray(objArr) || objArr.length === 0) return "";
const headers = [...Object.keys(objArr[0])];
return arrToCsv([headers, ...objArr.map(obj => headers.map(key => obj[key]))]);
};
const test = {
arrToCsv: {
method: arrToCsv,
data: [
["name1", 2, 3],
["name2", 4, 5],
["name3", 6, 7],
["name4", 8, 9],
["name5", 10, 11]
],
},
arrObjToCsv: {
method: arrObjToCsv,
data: [
{ name: "name1", age: 22, count: 3 },
{ name: "name2", age: 23, count: 4 },
{ name: "name3", age: 24, count: 5 },
{ name: "name4", age: 25, count: 6 },
{ name: "name5", age: 26, count: 7 }
]
},
};
o.innerHTML = ["arrToCsv", "arrObjToCsv"].map(m => (`<h3>Method: ${m}</h3><b>Input:</b>
${JSON.stringify(test[m].data, 0, 2)}
<b>Output:</b>
${test[m].method(test[m].data)}`
)).join`<hr>`;
</script>
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment