Javascript table string to array - javascript

I have a string that looks like:
<tr><td>Date</td><td>Value</td></tr>
<tr><td>2013-01-01</td><td>231.198</td></tr>
<tr><td>2013-02-01</td><td>232.770</td></tr>
<tr><td>2013-03-01</td><td>232.340</td></tr>
<tr><td>2013-04-01</td><td>231.485</td></tr>
<tr><td>2013-05-01</td><td>231.831</td></tr>
<tr><td>2013-06-01</td><td>232.944</td></tr>
<tr><td>2013-07-01</td><td>233.318</td></tr>
...which is of course essentially a table.
I'd like to dynamically convert this string into an array containing 2 arrays. One of dates, one of values.
[Edited in]
An array of objects with date and values would work too.

The following::
var input = // your string
var output = $(input).slice(1).map(function(i,el) {
var tds = $(el).find("td");
return { "date" : tds.eq(0).text(), "value" : tds.eq(1).text() };
}).get();
...will return an array of objects in this format:
[{"date":"2013-01-01","value":"231.198"}, {"date":"2013-02-01","value":"232.770"}, ... ]
If you'd like each value to be treated as a number you can convert it like so:
return { "date" : tds.eq(0).text(), "value" : +tds.eq(1).text() };
// add the unary plus operator ---------------^
Then the result will be:
[{"date":"2013-01-01","value":231.198}, {"date":"2013-02-01","value":232.77}, ... ]

While you've already accepted an answer, I thought I'd post a plain JavaScript solution (albeit largely because I spent time working on it, before Barmar pointed out that you're willing and able to use jQuery):
function cellContents(htmlStr, what) {
var _table = document.createElement('table');
_table.innerHTML = htmlStr;
var rows = _table.getElementsByTagName('tr'),
text = 'textContent' in document ? 'textContent' : 'innerText',
cells,
matches = {};
for (var w = 0, wL = what.length; w < wL; w++) {
matches[what[w]] = [];
for (var r = 1, rL = rows.length; r < rL; r++) {
cells = rows[r].getElementsByTagName('td');
matches[what[w]].push(cells[w][text]);
}
}
return matches;
}
var str = "<tr><td>Date</td><td>Value</td></tr><tr><td>2013-01-01</td><td>231.198</td></tr><tr><td>2013-02-01</td><td>232.770</td></tr><tr><td>2013-03-01</td><td>232.340</td></tr><tr><td>2013-04-01</td><td>231.485</td></tr><tr><td>2013-05-01</td><td>231.831</td></tr><tr><td>2013-06-01</td><td>232.944</td></tr><tr><td>2013-07-01</td><td>233.318</td></tr>";
console.log(cellContents(str, ['dates', 'values']));
JS Fiddle demo.

For a pure JavaScript solution you can try something like this (assuming str holds your string) :
var arrStr = str.replace(/<td>/g, "").replace(/<tr>/g, "").split("</td></tr>");
var arrObj = [];
var arrData
for (var i = 1; i < arrStr.length - 1; i++) {
arrData = arrStr[i].split("</td>");
arrObj.push({ Date: arrData[0], Value: arrData[1] })
}
It's a burte-force string replacement/split, but at the end arrObj will have array of objects.

if its a valid html table structure, wrap it between table tags, and use jquery to parse it.
then use jquery's selectors to find the columns.
e.g something like this ( pseudo code, havent tried it )
table = $(yourTableString);
dates = table.find("tr td:nth-child(1)");
values = table.find("tr td:nth-child(2)");

Using jQuery:
var table = $('<table>'+str+'</table>');
var result = {};
table.find('tr:gt(0)').each(function () {
var date = $(this).find("td:nth-child(1)").text();
var value = $(this).find("td:nth-child(2)").text();
result[date] = value;
}
:gt(0) is to skip over the header line. This will create an associative array object that maps dates to values. Assuming the dates are unique, this is likely to be more useful than two arrays or an array of objects.

Related

restructure CSV data to create correct format in JSON

I'm working with some CSV data. Right now the CSV has a column called 'characteristic' which is one of three types, and a column called 'value', which contains the numerical value for the characteristic.
I'd like to change the structure of the data so that the columns are the characteristics themselves, and the values fall directly under those columns.
Here are screenshots of the tables, for clarity:
Currently:
What I'd like:
I changed things manually to give an example. The actual table I'll need to change is thousands of lines, so I'm hoping I can do this programmatically in some way.
The reason I need to restructure is that I need to transform the CSV to JSON, and the JSON needs to look like this:
[
{
"country":"afghanistan",
"iso3":"afg",
"first_indicator":3,
"second_indicator":5,
"third_indicator":3
},
{
"country":"united states",
"iso3":"usa",
"first_indicator":8,
"second_indicator":6,
"third_indicator":7
},
{
"country":"china",
"iso3":"chn",
"first_indicator":6,
"second_indicator":0.7,
"third_indicator":2
}
]
So - is there any way to take my CSV as it is now (first screenshot), and transform it to the JSON I want, without doing it all manually?
I've done a lot of searching, and I think maybe I just don't know what to search for. Ideally I would use javascript for this, but any suggestions welcome.
Thank you.
I made a JSFiddle for you, something like this should be what you want.
JavaScript
function Country(name, short){
this["country"] = name;
this["iso3"] = short;
}
function getCountryByName(name) {
for(var i = 0; i < countries.length; i++){
var country = countries[i];
if(country["country"] == name){
return country;
}
}
return null;
}
var csv = "country,shortname,characteristics,value\nafghanistan,afg,first_characteristic,3\nunited states,usa,first_characteristic,8\nchina,chn,first_characteristic,6\nafghanistan,afg,second_characteristic,5\nunited states,usa,second_characteristic,6\nchina,chn,second_characteristic,0.7\nafghanistan,afg,third_characteristic,3\nunited states,usa,third_characteristic,7\nchina,chn,third_characteristic,2"
var rows = csv.split("\n");
var countries = [];
if(rows.length > 0){
var header = rows[0];
var columns = header.split(",");
var countryIndex = columns.indexOf("country");
var shortnameIndex = columns.indexOf("shortname");
var characteristicsIndex = columns.indexOf("characteristics");
var valueIndex = columns.indexOf("value");
for(var i = 1; i < rows.length; i++) {
var row = rows[i];
var columns = row.split(",");
var name = columns[countryIndex];
var short = columns[shortnameIndex];
var characteristic = columns[characteristicsIndex];
var value = columns[valueIndex];
var country = getCountryByName(name);
if(!country){
country = new Country(name, short);
countries.push(country);
}
country[characteristic.replace("characteristic", "indicator")] = +value;
}
}
console.log(countries);
console.log(JSON.stringify(countries));
Output from the last line is this:
[{"country":"afghanistan","iso3":"afg","first_indicator":"3","second_indicator":"5","third_indicator":"3"},
{"country":"united states","iso3":"usa","first_indicator":"8","second_indicator":"6","third_indicator":"7"},
{"country":"china","iso3":"chn","first_indicator":"6","second_indicator":"0.7","third_indicator":"2"}]
My suggestion is to convert the CSV to JSON first. You can use an online tool.
When you have the JSON you can write a Javascript code to modify the JSON in the format you want.

Create variables based on array

I have the following array and a loop fetching the keys (https://jsfiddle.net/ytm04L53/)
var i;
var feeds = ["test_user_201508_20150826080829.txt:12345","test_user_list20150826:666","test_list_Summary20150826.txt:321"];
for (i = 0; i < feeds.length; i++) {
var feed = feeds[i];
alert(feed.match(/\d+$/));
}
The array will always contain different number of keys, What I would like to do is either use these keys as variables and assign the value after the : semicolon as its value or just create a new set of variables and assign the values found on these keys to them.
How can I achieve this? so that I can then perform some sort of comparison
if (test_user > 5000) {dosomething}
update
Thanks for the answers, how can I also create a set of variables and assign the array values to them? For instance something like the following.
valCount(feeds.split(","));
function valCount(t) {
if(t[0].match(/test_user_.*/))
var testUser = t[0].match(/\d+$/);
}
Obviously there is the possibility that sometimes there will only be 1 key in the array and some times 2 or 3, so t[0] won't always be test_user_
I need to somehow pass the array to a function and perform some sort of matching, if array key starts with test_user_ then grab the value and assign it to a define variable.
Thanks guys for all your help!
You can't (reasonably) create variables with dynamic names at runtime. (It is technically possible.)
Instead, you can create object properties:
var feeds = ["test_user_201508_20150826080829.txt:12345","test_user_list20150826:666","test_list_Summary20150826.txt:321"];
var obj = {};
feeds.forEach(function(entry) {
var parts = entry.split(":"); // Splits the string on the :
obj[parts[0]] = parts[1]; // Creates the property
});
Now, obj["test_user_201508_20150826080829.txt"] has the value "12345".
Live Example:
var feeds = ["test_user_201508_20150826080829.txt:12345","test_user_list20150826:666","test_list_Summary20150826.txt:321"];
var obj = {};
feeds.forEach(function(entry) {
var parts = entry.split(":");
obj[parts[0]] = parts[1];
});
snippet.log(obj["test_user_201508_20150826080829.txt"]);
<!-- Script provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
You can do it like this, using the split function:
var i;
var feeds = ["test_user_201508_20150826080829.txt:12345","test_user_list20150826:666","test_list_Summary20150826.txt:321"];
for (i = 0; i < feeds.length; i++) {
var feed = feeds[i];
console.log(feed.split(/[:]/));
}
This outputs:
["test_user_201508_20150826080829.txt", "12345"]
["test_user_list20150826", "666"]
["test_list_Summary20150826.txt", "321"]
Use the split method
var feeds = ["test_user_201508_20150826080829.txt:12345","test_user_list20150826:666","test_list_Summary20150826.txt:321"];
feedMap = {}
for (i = 0; i < feeds.length; i++) {
var temp = feeds[i].split(':');
feedMap[temp[0]] = temp[1];
}
Yields:
{
"test_user_201508_20150826080829.txt":"12345",
"test_user_list20150826":"666",
"test_list_Summary20150826.txt":"321"
}
And can be accessed like:
feedMap["test_user_201508_20150826080829.txt"]
Here is a codepen
it is not very good idea but if you really need to create variables on-the-run here's the code:
for (i = 0; i < feeds.length; i++)
{
var feed = feeds[i];
window[feed.substring(0, feed.indexOf(":"))] = feed.match(/\d+$/);
}
alert(test_user_201508_20150826080829)
Of course you cannot have any variable-name-string containing banned signs (like '.')
Regards,
Michał

How to convert variable to two dimensional array using java script

I have a variable which contains data like this
var values = "VItDTotal,123,234,234,2345,1234,123,435,10,TestCase,123,234,234,2345,1234,123,435,5"
and I want to convert this string of data to a two dimensional array like this
[VItDTotal,123,234,234,2345,1234,123,435,10] //1st row
[TestCase, 123,234,234,2345,1234,123,435,5] //2nd row
How can I convert a JS variable to a two dimensional array?
I want to append these values to a datatable, how can I achieve this by using jQuery?
I hope this might help...
var values = "VItDTotal,123,234,234,2345,1234,123,435,10,TestCase,123,234,234,2345,1234,123,435,5"
var splittedArray = values.split(',')
var resultArray = new Array();
var resultKey = -1;
for(var i=0; i<splittedArray.length; i++) {
if(isNaN(splittedArray[i])) {
resultKey++;
resultArray[resultKey] = new Array();
resultArray[resultKey].push(splittedArray[i])
} else {
resultArray[resultKey].push(splittedArray[i])
}
}
I work this way:
//get the index where ",TestCase" is
var index = values.indexOf(",TestCase");
//create two arrays to the values
var part_one = [], part_two = [];
//slice the value from 0 to index and push part one
part_one.push(values.slice(0,index));
//slice the value from index+1 to the end and push part two
part_two.push(values.slice(index+1, values.length));
Not my favourite, but, are you after something like this?
var values = ["VItDTotal",123,234,234,2345,1234,123,435,10,"TestCase",123,234,234,2345,1234,123,435,5];
var vals = [values.
join(",").
replace(/,([a-z]+)(?!.*[a-z]+)/gi, " devider $1").
split(/\s+devider\s+/gi)];
console.log(vals);

Javascript: How to re-arrange content display of text field?

I have a text field (not a date field) who contain simply a value such "2013-08-27" and my goal would be to reverse the order and get "27-08-2013". So is matter to re-arrange the content but I don't have enough javascript knowledge. I tried using some "date" variable but without success much probably because my field is not a date field.
The html related to the field look like this:
<input type="text" value="2013-08-27" name="my_field" id="my-field" readonly="">
If you can give me an example of code based of this:
var my_field = document.getElementById('my_field');
thank
PS: I precise I don't have access to html of this field because is located to a remote server. I can only interact by adding code in a JS file planned for that. The field have also a "readonly" property because is not planned for be modified.
This code should do the trick:
var revert = function(str) {
var parts = str.split("-");
var newArr = [];
for(var i=parts.length-1; p=parts[i]; i--) {
newArr.push(p);
}
return newArr.join("-");
}
var replaceValueInInputField = function(id) {
var field = document.getElementById(id);
field.value = revert(field.value);
}
var replaceValueInDomNode = function(id) {
var el = document.getElementById(id);
var value = el.innerHTML, newValue = '';
var matches = value.match(/(\d{4})-(\d{2})\-(\d{2})/g);
for(var i=0; m=matches[i]; i++) {
value = value.replace(m, revert(m));
}
el.innerHTML = value;
}
replaceValueInInputField("my-field");
replaceValueInDomNode("my-field2");
jsfiddle http://jsfiddle.net/qtDjF/2/
split('-') will return an array of number strings
reverse() will order array backwards
join("-") will join array back with '-' symbol
var my_field_value = document.getElementById('my_field').value;
my_field_value.split('-').reverse().join("-");
You can use the split function.
var my_field = document.getElementById('my_field').split("-");
the var my_field will be an array of string like : "YYYY,mm,dd"
and then you can re-arrange it in the order you want.
Try this
var date = document.getElementById("my-field").value;
//alert(date);
var sp = date.split("-");
alert(sp[2]+"-"+sp[1]+"-"+sp[0]);
With Jquery
var parts =$('#my-field').val().split("-");
$('#my-field').val(parts[2]+"-"+parts[1]+"-"+parts[0]);
Simple regex:
var res;
test.replace(/(\d\d\d\d)-(\d\d)-(\d\d)/,function(all,a,b,c){res=c+"-"+b+"-"+a;});
JSFiddle: http://jsfiddle.net/dzdA7/8/
You could try splitting the string into array and inverting it's items in a loop:
var my_field = document.getElementById('my_field').value.split("-"),
length = my_field.length,
date = [];
for(i = length - 1; i >= 0; i--){
date.push(my_field[i]);
}
console.log(date.toString().replace(/,/g,"-"));

Dynamically create a two dimensional Javascript Array

Can someone show me the javascript I need to use to dynamically create a two dimensional Javascript Array like below?
desired array contents:
[["test1","test2","test3","test4","test5"],["test6","test7","test8","test9","test10"]]
current invalid output from alert(outterArray):
"test6","test7","test8","test9","test10","test6","test7","test8","test9","test10"
JavaScript code:
var outterArray = new Array();
var innerArray = new Array();
var outterCount=0;
$something.each(function () {
var innerCount = 0;//should reset the inner array and overwrite previous values?
$something.somethingElse.each(function () {
innerArray[innerCount] = $(this).text();
innerCount++;
}
outterArray[outterCount] = innerArray;
outterCount++;
}
alert(outterArray);
This is pretty cut and dry, just set up a nested loop:
var count = 1;
var twoDimensionalArray =[];
for (var i=0;i<2;i++)
{
var data = [];
for (var j=0;j<5;j++)
{
data.push("Test" + count);
count++;
}
twoDimensionalArray.push(data);
}
It sounds like you want to map the array of text for each $something element into an outer jagged array. If so then try the following
var outterArray = [];
$something.each(function () {
var innerArray = [];
$(this).somethingElse.each(function () {
innerArray.push($(this).text());
});
outterArray.push(innerArray);
});
alert(outterArray);
A more flexible approach is to use raw objects, they are used in a similar way than dictionaries. Dynamically expendables and with more options to define the index (as string).
Here you have an example:
var myArray = {};
myArray[12]="banana";
myArray["superman"]=123;
myArray[13]={}; //here another dimension is created
myArray[13][55]="This is the second dimension";
You don't need to keep track of array lengths yourself; the runtime maintains the ".length" property for you. On top of that, there's the .push() method to add an element to the end of an array.
// ...
innerArray.push($(this).text());
// ...
outerArray.push(innerArray);
To make a new array, just use []:
innerArray = []; // new array for this row
Also "outer" has only one "t" :-)
[SEE IT IN ACTION ON JSFIDDLE] If that $something variable is a jQuery search, you can use .map() function like this:
var outterArray = [];
var outterArray = $('.something').map(function() {
// find .somethingElse inside current element
return [$(this).find('.somethingElse').map(function() {
return $(this).text();
}).get()]; // return an array of texts ['text1', 'text2','text3']
}).get(); // use .get() to get values only, as .map() normally returns jQuery wrapped array
// notice that this alert text1,text2,text3,text4,text5,text6
alert(outterArray);​
// even when the array is two dimensional as you can do this:
alert(outterArray[0]);
alert(outterArray[1]);
HTML:
<div class="something">
<span class="somethingElse">test1</span>
<span class="somethingElse">test2</span>
<span class="somethingElse">test3</span>
</div>
<div class="something">
<span class="somethingElse">test4</span>
<span class="somethingElse">test5</span>
<span class="somethingElse">test6</span>
</div>
Here you can see it working in a jsFiddle with your expected result: http://jsfiddle.net/gPKKG/2/
I had a similar issue recently while working on a Google Spreadsheet and came up with an answer similar to BrianV's:
// 1st nest to handle number of columns I'm formatting, 2nd nest to build 2d array
for (var i = 1; i <= 2; i++) {
tmpRange = sheet.getRange(Row + 1, Col + i, numCells2Format); // pass/fail cells
var d2Arr = [];
for (var j = 0; j < numCells2Format; j++) {
// 1st column of cells I'm formatting
if ( 1 == i) {
d2Arr[j] = ["center"];
// 2nd column of cells I'm formatting
} else if ( 2 == i ) {
d2Arr[j] = ["left"];
}
}
tmpRange.setHorizontalAlignments( d2Arr );
}
So, basically, I had to make the assignment d2Arr[index]=["some string"] in order to build the multidimensional array I was looking for. Since the number of cells I wanted to format can change from sheet to sheet, I wanted it generalized. The case I was working out required a 15-dimension array. Assigning a 1-D array to elements in a 1-D array ended up making the 15-D array I needed.
you can use Array.apply
Array.apply(0, Array(ARRAY_SIZE)).map((row, rowIndex) => {
return Array.apply(0, Array(ARRAY_SIZE)).map((column, columnIndex) => {
return null;
});
});`

Categories

Resources