Converting from CSV string to Json in javascript - javascript

I am trying to convert a csv string to json in javascript.
I referred to the following link first answer: "What Is The Best Way To Convert From Csv To Json When Commas And Quotations May.
However, when I try that, the header contains a comma so I am not able to render a data Table.
const csvToJson = (str, headerList, quotechar = '"', delimiter = ',') => {
const cutlast = (_, i, a) => i < a.length - 1;
// const regex = /(?:[\t ]?)+("+)?(.*?)\1(?:[\t ]?)+(?:,|$)/gm; // no variable chars
const regex = new RegExp(`(?:[\\t ]?)+(${quotechar}+)?(.*?)\\1(?:[\\t ]?)+(?:${delimiter}|$)`, 'gm');
const lines = str.split('\n');
const headers = headerList || lines.splice(0, 1)[0].match(regex).filter(cutlast);
const list = [];
for (const line of lines) {
const val = {};
for (const [i, m] of [...line.matchAll(regex)].filter(cutlast).entries()) {
// Attempt to convert to Number if possible, also use null if blank
val[headers[i]] = (m[2].length > 0) ? Number(m[2]) || m[2] : null;
}
list.push(val);
}
return list;
}
const testString = `name,age,booktitle
John,,Hello World
Mary,3,""Alas, What Can I do?""
Joseph,5,"Waiting, waiting, waiting"
"Donaldson Jones" , six, "Hello, friend!"`;
console.log(csvToJson(testString));
console.log(csvToJson(testString, ['foo', 'bar', 'baz']));
I have also tried to figure out RegExp written but could not understand it.
Can anybody tell me how to remove a comma from that answer or a better suggestion?

Looks like your problem is the attribute names from your current solution. They sometimes have "," in the end.
If that is the case, the simplest solution is just to remove them using the replace method.
console.log( "something,".replace( ",", "" ) )
console.log( "age".replace( ",", "" ) )

Related

Can this problem be solved using functional programming only?

The prompt was:
Create a function that takes in a string and returns a "URL version" of the string. This simply involves replacing the spaces with %20.
It asked to solve the problem using recursion and using .replace is not allowed.
Here is my solution but I understand the ouputArray is being mutated. Is there any other way to solve this without a mutation?
let inputString = "hello world I am fine";
let outputArray = [];
let stringToUrl = (inputString, n) => {
inputArray = [...inputString]
if(n < inputArray.length) {
if(inputArray[n] !== " ") {
outputArray.push(inputArray[n])
return stringToUrl(inputArray, n+1)
}
else {
outputArray.push("%20")
return stringToUrl(inputArray, n+1)
}
}
return outputArray.join('');
}
console.log(stringToUrl(inputString, 0))
Yes, you can do this with FP. In keeping with How do I ask and answer homework questions?, I won't reply with code, but with pointers.
If you weren't doing this with FP (but still had to write it yourself rather than using the string replace method, etc.), you'd probably use a loop building up a new string by looping through the original string character by character and either adding the original character to the new string or adding %20 to it.
In FP, loops are often done via recursion, and your instructions are to use recursion, so we'll do that instead.
Your function should handle the first character in the string it's given (either keeping it or replacing it with %20), and if that character is the only character, just return that updated "character;" otherwise, it should return the updated character followed by the result of passing the rest of the string (all but that first character) through your function again. That will work through the entire string via recursion, building up the new string. (No need for arrays, string concatenation and substring should be fine.)
Here I have made some changes to your code. Hope this solves your problem.
I don't have to use the second array but make changes to the original array.
let inputString = "hello world I am fine";
let stringToUrl = (inputString, n) => {
inputArray = [...inputString]
if(n < inputArray.length) {
if(inputArray[n] === " ") {
inputArray[n] = "%20"
return stringToUrl(inputArray, n+1)
}
else {
return stringToUrl(inputArray, n+1)
}
}
return inputArray.join('');
}
console.log(stringToUrl(inputString, 0))
const replace = (char: string) => char === ' ' ? '%20' : char;
const convert = (str: string, cache = ''): string => {
const [head, ...tail] = str;
return head
? convert(
tail.join(''),
cache.concat(replace(head))
)
: cache
}
const result = convert("hello world I am fine") // hello%20world%20I%20am%20fine
Playground
I hope this task is not language agnostic, because JS is not best choise in terms of recursion optimization.
One option to do that could be using a call to stringToUrl and use an inner recursive function making use of default parameters passing the values of the variables as function arguments.
For example using an arrow function, and also passing a function as a parameter that does a check to either add %20 to the array with final characters:
const stringToUrl = str => {
const func = (
s,
r = "",
c = s.charAt(0),
f = () => r += c === ' ' ? '%20' : c
) => s.length ? f() && func(s.substr(1), r) : r
return func(str)
}
console.log(stringToUrl("hello world I am fine"));
Output
hello%20world%20I%20am%20fine
const stringToUrl = str => {
const func = (
s,
r = "",
c = s.charAt(0),
f = () => r += c === ' ' ? '%20' : c
) => s.length ? f() && func(s.substr(1), r) : r
return func(str)
}
[
"",
" ",
" ",
"hello world I am fine"
].forEach(s =>
console.log(`[${s}] --> ${stringToUrl(s)}`)
);

How to convert string to array of object?

I have the following string:
"[['ABB','ACC','ADD'],['FGG','FHH','FJJJ'],['MNN','MOO','MPP']]"
and I want to convert it to array of object
[['ABB','ACC','ADD'],['FGG','FHH','FJJJ'],['MNN','MOO','MPP']]
I've tried to do many things but I could not
function nextQuess() {
var ffa = JSON.stringify("<%- hola %>"); // from ejs variable "[['ABB','ACC','ADD'],['FGG','FHH','FJJJ'],['MNN','MOO','MPP']]"
// var ff = JSON.parse([ffa])
// console.log('hello', ff);
console.log("Hello", ffa);
}
You need to replace ' by " and then parse
'(.*?)'(?=(,|\])
'(.*?)' - Match ' followed by anything zero more time ( Lazy mode ) ( Capture group 1)
(?=(,|\])) - Match must be followed by , or ]
let str = "[['ABB','ACC','ADD'],['FGG','FHH','FJJJ'],['MNN','MOO','MPP']]"
let replacedString = str.replace(/'(.*?)'(?=(,|\]))/g, "\"$1\"")
let final = JSON.parse(replacedString)
console.log(final)
Use JSON.stringify(json) and then JSON.parse()
let jsonString = JSON.stringify([['ABB','ACC','ADD'],['FGG','FHH','FJJJ'],['MNN','MOO','MPP']]);
let array = JSON.parse(jsonString);
console.log(array);
Or you can also try eval() method
let jsonArray = eval([['ABB','ACC','ADD'],['FGG','FHH','FJJJ'],['MNN','MOO','MPP']]);
console.log(jsonArray);

How to replace/remove some part of a string

I have a string in which i want to remove some part.
1) below is the string( Encrypted message)
##_/profiles/c3ed4acd-b3be-487e-81b4-a27643745d^^____User1__###^^^ says hello to ##_/profiles/d3ac3c5a-8a9f-4640-8563-127674d93e^^____User2__###^^^
I want to get below 2 things from this
a) A string
#User1 says to #User2
2) A json object like
{
"c3ed4acd-b3be-487e-81b4-a27643745d":"User1",
"d3ac3c5a-8a9f-4640-8563-127674d93e":"User2"
}
First I tried to get string and used below approach using regex
I have tried it by doing like this
var str = "##___/profiles/c3ed4acd-b3be-487e-81b4-a27643745d__^^____User1__###^^^ says to ##___/profiles/d3ac3c5a-8a9f-4640-8563-127674d93e__^^____User2__###^^^"
var rx = /(^##___|,###^^^)/; // start with ##___ and end with ###^^^
var expectedString = str.replace(/(^##___|,###^^^)/g, "");
console.log(expectedString);
But this is just replace first occurance of
There are some fundamental problems in your code
you have to escape the ^ character as \^
you don't even use your rx variable
pipe character | means or, not start with and end with
try this:
// a)
var str = "##___/profiles/c3ed4acd-b3be-487e-81b4-a27643745d__^^____User1__###^^^ says to ##___/profiles/d3ac3c5a-8a9f-4640-8563-127674d93e__^^____User2__###^^^"
var rx = /##___([^_]+)__\^\^____([^_]+)__###\^\^\^/g;
var expectedString = str.replace(rx, "#$2");
console.log(expectedString);
// b)
var list = {};
while ((m = rx.exec(str)) !== null) {
if (m.index === rx.lastIndex) {
rx.lastIndex++;
}
list[m[1]] = m[2];
}
console.log(list);

Nodejs : RegExp returns nothing

I'm trying to extract the names of electrodes and their values from the Emotiv output. However the code below returns nothing.
I'm a newbie in nodejs. I tried doing it on a single line with Regex but it's too complicated i couldn't get it right. I've succeeded in grabbing the whole line but not the values.
Here is my code :
var str = '"levels":{"F3":7094,"FC6":8209,"P7":12165,"T8":5380,"F7":1356,"F8":2043,"T7":11882,"P8":10117,"AF4":13257,"F4":6134,"AF3":13527,"O2":9686,"O1":871,"FC5":1808},"' ;
const reg = new RegExp('.{2}\w\"\:\d{3,5}/g');
var test = str.match(reg) ;
if (test)
console.log(test[1]) ;
I expect an output to be F3 : 8209 and so on for the 14 electrodes.
I know this is not exactly answering the RegExp question but this rewrite should take get you working faster.
const text = '"levels":{"F3":7094,"FC6":8209,"P7":12165,"T8":5380,"F7":1356,"F8":2043,"T7":11882,"P8":10117,"AF4":13257,"F4":6134,"AF3":13527,"O2":9686,"O1":871,"FC5":1808},"';
let json = "{" + text.substring(0, text.length - 2) + "}"
let obj = JSON.parse(json)
for (const [key, value] of Object.entries(obj.levels)) {
console.log(`${key} ${value}`);
}
I've also come up with a new RegExp that I think will give you what you want.
const text = '"levels":{"F3":7094,"FC6":8209,"P7":12165,"T8":5380,"F7":1356,"F8":2043,"T7":11882,"P8":10117,"AF4":13257,"F4":6134,"AF3":13527,"O2":9686,"O1":871,"FC5":1808},"';
let regexp = /\"([^\"]{2,3})\"\:(\d{3,5})/g
let r = null
do {
r = regexp.exec(text)
if (r) console.log(`${r[1]} ${r[2]}`);
} while (r)

Split after regex max without losing delimeter

I'd like to transform a string like:
hello!world.what?up into ["hello!", "world.", "what?", "up"]
.split(/[?=<\.\?\!>]+/) is close to what I'm after, which returns:
["hello", "world", "what", "up"]
.split(/(?=[\?\!\.])/) is a bit closer yet, which returns:
["hello", "!world", ".what", "?up"]
This does the trick, but it's not pretty:
.split(/(?=[\?\!\.])/).map((s, idx, arr) => { (idx > 0) s = s.slice(1); return idx < arr.length - 1 ? s + arr[idx+1][0] : s }).filter(s => s)
How would I rephrase this to achieve the desired output?
Edit: Updated question.
Not sure of the real requirement but to accomplish what you want you could use .match instead of .split.
const items =
'hello!world.what?'.match(/\w+\W/g);
console.log(items);
update after comment
You could add a group for any character you want to use as the terminator for each part.
const items =
'hello!world.what?'.match(/\w+[!.?]/g);
console.log(items);
additional update
the previous solution would only select alphanumeric chars before the !.?
If you want to match any char except the delimiters then use
const items =
'hello!world.what?up'.match(/[^!.?]+([!.?]|$)/g);
console.log(items);
One solution could be first to use replace() for add a token after each searched character, then you can split by this token.
let input = "hello!world.what?";
const customSplit = (str) =>
{
let token = "#";
return str.replace(/[!.?]/g, (match) => match + "#")
.split(token)
.filter(Boolean);
}
console.log(customSplit(input));

Categories