0

I am trying to create below data result as key/value pair , how we can achieve that task using JS split functionality got little stuck here.

main.js

const data = [{
        "Row ID  O ID    O Date  Ship Date   Ship Type": "1   PA-152156   11/9/20 01/19/16"
    }

]
    function buildArray(data) {
      for(item in arr) {
      let string = item;
      let array  = string
      .replace(/" "\s/g, '####')
      .split(' ')
      .map(pair => {
        let split = pair.split('####');
        return { key: split[0], value: split[1] };
      });
     }
    }

console.log(buildArray(data));

expected output

[{
    "Row ID": 1,
    "O ID": "PA-152156",
    "O Date": "11/9/20",
    "Ship Date": "01/19/16"
}]

tsvFile data

Row ID  O ID    O Date  Ship Date   Ship Type   Customer ID Customer Name   Seg Country City    State   Zip Code    Region  Product ID  Category    Sub-Category    Product Name    Sales   Quantity    Discount    Profit
1   PA-152156   11/9/20 01/19/16    Second Class    CG-125  Clay bute   Consumer    United States   Henderson   Kentucky    42420   South   FUR-BO-10001798 Furniture   Bookcases   Bush, Somerset Collection Bookcase? 261.96  2   0   41.9136
2
  • Is there a set number of spaces between each column header? You could split off of that if so, but I ultimately the data structure here seems really frail. Can the data not come in as a CSV? Commented Apr 23, 2020 at 21:20
  • @coloradocolby i am reading data from tsv file where i build an array as i added as data in the example above , now ask is to build key value pair Commented Apr 23, 2020 at 21:23

1 Answer 1

1

We could start with your original data and write a function that converts a TSV string (with headers) into an array of objects.

This tsv2arr (slightly altered from an earlier answer) does this by first trimming any leading or trailing whitespace, splitting on new-lines, and splitting each line on tabs. The first line's output becomes the header field names and the remaining ones get reduced into objects by taking each value and pairing it with the header at the same index. Values that look like numbers are converted into numbers; this might convert some things you don't want to convert, but you could then post-process it if you need to change them.

The code is reasonably simple:

const tsv2arr = (tsv) => {
  const [headers, ...rows] = tsv .trim () .split ('\n') .map (r => r .split ('\t'))
  return rows .reduce ((a, r) => [
    ... a, 
    Object .assign (... (r .map (
      (x, i, _, c = x.trim()) => ({[headers [i].trim()]: isNaN(c) ? c : Number(c)})
    )))
  ], [])
}

const tsv = `
Row ID	O ID    	O Date	Ship Date	Ship Type	Customer ID	Customer Name	Seg      	Country	        City    	State   	Zip Code	Region	Product ID	Category	Sub-Category	Product Name                    	Sales	Quantity	Discount	Profit
1	PA-152156	11/9/20	01/19/16	Second Class	CG-125  	Clay bute	Consumer	United States	Henderson	Kentucky	42420   	South	FUR-BO-10001798	Furniture	Bookcases	Bush, Somerset Collection Bookcase?	261.96	2        	0        	41.9136
2	ST-621973	8/9/20	02/10/16	First Class	XY-139  	Foobar Inc	Consumer	United States	Madison 	Wisconsin	53702   	Midwest	FUR-SO-10003869	Furniture	Sofas   	Tyler, Some Random Sofa Name    	963.85	1        	0        	265.89
3	MQ-169437	12/7/20	03/15/16	Second Class	CG-125  	Clay bute	Consumer	United States	Henderson	Kentucky	42420   	South	FUR-DE-10005309	Furniture	Desk    	Adams, Some Random Desks Name?  	654.13	1        	0        	143.28
`


console .log (
  tsv2arr (tsv)
)
.as-console-wrapper {min-height: 100% !important; top: 0}


Edit: Added a trim to the cells. This may not be necessary; it is probably only an artifact of my formatting the input to line up the tabs. But it's difficult to imagine it hurting anything and it might help in certain circumstances. Note that there are many extra spaces in the source text to make the columns line up right on the page. They are, of course, entirely irrelevant, and this trim gets rid of them.

Alternative

If you really want to start with that input format, you can write something like this:

const data = [
  {"Row ID	O ID	O Date	Ship Date	Ship Type": "1	PA-152156	11/9/20	01/19/16	Second Class"},
  {"Row ID	O ID	O Date	Ship Date	Ship Type": "2	ST-621973	8/9/2	02/10/16	First Class"}
]

const buildObj = (kv) =>
  Object .entries (kv) .map (([k, v]) => {
    const keys = k .split ('\t')
    const vals = v .split ('\t')
    return Object .assign (... keys .map ((k, i) => ({[k]: vals [i]})))
  })

console .log (
  data .flatMap (buildObj)
)

But this format makes very little sense to me, at least as a transport format. If nothing else, it's quite redundant.

I suspect that you have a problem where you don't have the tabs you thought you had. Programmers' text editors are often configured to replace tabs with spaces; that might be what's happening here. What you pasted into the question does not include tabs, for instance.

I would suggest you try fixing your input problems and use something more like the original answer. This is a work-around for some strange data that likely is an artifact of your development/display process rather than something fundamental.

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

5 Comments

How do i create the string you have declared using const tsv , i am reading the file and converting it to string const tsvFileData = fs.readFileSync('./filename1.tsv'); const tsvToStr = tsvFileData.toString(); and its throwing error tsv.trim is not a fucntion
returning result like [ { "Row ID O ID O Date Ship Date Ship Type Customer ID Customer Name Seg Country City State Zip Code Region Product ID Category Sub-Category Product Name Sales Quantity Discount Profit": "1 PA-152156 11/9/20 01/19/16 Second Class CG-125 Clay bute Consumer United States Henderson Kentucky 42420 South FUR-BO-10001798 Furniture Bookcases Bush, Somerset Collection Bookcase? 261.96 2 0 41.9136" }]
I have no idea how you're getting that odd format. I don't know if this will help: fs.readFileSync('./filename1.tsv').toString('utf8'). If not, then I don't understand your input format. But that intermediate format is pretty horrible. We could easily modify the code to handle it. But what would it look like with additional records?
i tried toString result is still the same not sure how it is working in the snippet you provided , thats the format i have the way you assigned it to tsv variable
@hussain: I added an alternative, which might possibly help. But I expect that the problem has more to do with the tabs in your input.

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.