Extract JSON table from JSON string element - javascript

I get this JSON in response from server:
{
"tab":[
"[[\"2018\",11,\"19\",\"16\",\"13\"],null,null,null,null,null,\"40\"]",
"[[\"2018\",11,\"19\",\"16\",\"19\"],null,null,null,null,null,\"56\"]",
"[[\"2018\",11,\"19\",\"16\",\"21\"],null,null,null,null,\"57\",null]"
]
}
I know, that I can get first element of tab table returned using $.tab[1]. The returned element is a string that holds a table - first element of this table is another table holding a date. The question is what JSON Path expression should I use in order to extract year value from the inner table or one of those numbers at the end (40, 56, 57)?

I'm not sure what you mean when you say you can get the first element with $.tab[1]. Are you using jQuery? Even so, that doesn't seem to make any sense. Regardless, you can parse those inner tables and access them normally as arrays:
var results = {
"tab":[
"[[\"2018\",11,\"19\",\"16\",\"13\"],null,null,null,null,null,\"40\"]",
"[[\"2018\",11,\"19\",\"16\",\"19\"],null,null,null,null,null,\"56\"]",
"[[\"2018\",11,\"19\",\"16\",\"21\"],null,null,null,null,\"57\",null]"
]
};
// you can refactor this as a method for more convenient usage, this is just a demo
var row = JSON.parse(results.tab[0]);
// now you just have a multi-dimensional array, use it as normal
console.log(row[0][0]); //year
console.log(row[6]); //number

Related

Copy a specific column from a csv file to an array using javascript

I have a little problem that is how to Copy a specific column from a csv file to an array using javascript
thank you :)
csv data is best represented in javascript using an array of arrays (a 2-dimension array) with primary indices representing rows (records in data-base terminology) and the inner indices representing column cells for that row (fields in data-base terminology).
Thus, this csv data:
"name","age","height"
"John",22,1.9
"Jane",21,1.9
"Joe",23,1.8
would be represented as:
[["name","age","height"],["John",22,1.9],["Jane",21,1.9],["Joe",23,1.8]];
in a javascript array.
If you have an array like that, you can extract a column (the first column, inner array index [0] in this case, easily with:
const columnArray = [];
for (let i=0; i<csvArray.length; i++){columnArray.push(array1[i][0])}
// columnArray now holds ["name","John","Jane","Jo"];
// use [1] instead of [0] for the second column, [2] for the third, etc.;
If you don't yet have the array, you will have to form one. Many frameworks may do this for you but it is easily achieved once you have the csv data inside a variable:
const csvFileData = // read from textarea or file;
const csvArray = csvFileData.split('\n')
// csvArray holds ['"name","age","height"', '"John",22,1.9', '"Jane",21,1.9', '"Joe",23,1.8'] at this stage;
// split the inner arrays to arrays of cell data;
for (let i=0; i<array1.lengthl; i++){array[i]=array[i].split(',')}
// We've replaced each element with an array holding the component cells of what was previously a row;
// csvArray now holds:
[["name","age","height"],["John",22,1.9],["Jane",21,1.9],["Joe",23,1.8]];
That final array can now be processed to extract the required column as shown above.
Finally, all this assumes you can get the csv data into a variable (remember it has line breaks). Fetch() is probably the standard way but a simple (if dirty) alternative I often use is to assign the value of an html textarea into which I have pasted the csv file contents into, directly to a variable:
const csvFileData = document.getElementById('textareaOnWebPage').value;

What is the best way to itterate over key value pairs nested in an index using javascript?

I am trying to sort sets of associated key value pairs. They look like this:
{"word":"a","votes":9326,"userMade":"FALSE","limiter":"FALSE"},
But organized into labeled subsets of preferably a string or perhaps an index if necessary.
The data-set is a vote-per-use table of most used english words being parsed into pages.
I will be appending them as text to other html elements due to the constraints my use case, makes it a bit tricky, however, for an example I could work with a simple console.log of the page value followed by the console.log of every word value stored within that page. I need the order preserved. so probably indexed. I will also need to be able to sort each page by the votes value, but I think I can figure the rest out for that.
I have found tutorials on how to search through key-value pairs, but I cannot find how to do all of the following with one solution:
A: access the value of word
B: maintain the order of the data-set, allowing me to append them to the matching html element
C: allows me the opportunity to change which set of elements I am appending to when i have finished looping through a single member of the parent index (the one recording the page)
I imagine it is some combination of for/of and for/in, but I'm getting a headache. Please help?
addl info:
function would run at app startup or when the dataset being examined is changed.
function would take a large dataset filled with around 200 page number values, each with 60+ sets of data like the one listed above, the contents of a single page index for example:
{"word":"a","votes":9326,"userMade":"FALSE","limiter":"FALSE"},
{"word":"aaron","votes":4129,"userMade":"FALSE","limiter":"FALSE"},
{"word":"abandoned","votes":1289,"userMade":"FALSE","limiter":"FALSE"},
{"word":"abc","votes":5449,"userMade":"FALSE","limiter":"FALSE"},
{"word":"aberdeen","votes":641,"userMade":"FALSE","limiter":"FALSE"},
{"word":"abilities","votes":2210,"userMade":"FALSE","limiter":"FALSE"},
{"word":"ability","votes":7838,"userMade":"FALSE","limiter":"FALSE"},
{"word":"able","votes":8649,"userMade":"FALSE","limiter":"FALSE"},
{"word":"aboriginal","votes":1837,"userMade":"FALSE","limiter":"FALSE"},
{"word":"abortion","votes":3232,"userMade":"FALSE","limiter":"FALSE"},
{"word":"about","votes":9295,"userMade":"FALSE","limiter":"FALSE"},
{"word":"above","votes":8818,"userMade":"FALSE","limiter":"FALSE"},
{"word":"abraham","votes":867,"userMade":"FALSE","limiter":"FALSE"},
{"word":"abroad","votes":4969,"userMade":"FALSE","limiter":"FALSE"},
{"word":"abs","votes":2415,"userMade":"FALSE","limiter":"FALSE"},
{"word":"absence","votes":4934,"userMade":"FALSE","limiter":"FALSE"},
{"word":"absent","votes":2937,"userMade":"FALSE","limiter":"FALSE"},
{"word":"absolute","votes":5251,"userMade":"FALSE","limiter":"FALSE"},
{"word":"absolutely","votes":5936,"userMade":"FALSE","limiter":"FALSE"},
{"word":"absorption","votes":285,"userMade":"FALSE","limiter":"FALSE"},
{"word":"abstract","votes":7946,"userMade":"FALSE","limiter":"FALSE"},
{"word":"abstracts","votes":1907,"userMade":"FALSE","limiter":"FALSE"},
{"word":"abuse","votes":7238,"userMade":"FALSE","limiter":"FALSE"},
{"word":"academic","votes":7917,"userMade":"FALSE","limiter":"FALSE"},
{"word":"academics","votes":1706,"userMade":"FALSE","limiter":"FALSE"},
{"word":"academy","votes":6755,"userMade":"FALSE","limiter":"FALSE"},
{"word":"acc","votes":6469,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accent","votes":1020,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accept","votes":7547,"userMade":"FALSE","limiter":"FALSE"},
{"word":"acceptable","votes":4907,"userMade":"FALSE","limiter":"FALSE"},
{"word":"acceptance","votes":7273,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accepted","votes":7684,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accepting","votes":1789,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accepts","votes":1535,"userMade":"FALSE","limiter":"FALSE"},
{"word":"access","votes":9031,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accessed","votes":2932,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accessibility","votes":5702,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accessible","votes":5662,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accessing","votes":2096,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accessories","votes":8875,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accessory","votes":5661,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accident","votes":5664,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accidents","votes":2991,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accommodate","votes":1807,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accommodation","votes":8059,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accommodations","votes":3885,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accompanied","votes":2532,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accompanying","votes":664,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accomplish","votes":1070,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accomplished","votes":2419,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accordance","votes":6434,"userMade":"FALSE","limiter":"FALSE"},
{"word":"according","votes":8282,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accordingly","votes":3003,"userMade":"FALSE","limiter":"FALSE"},
{"word":"account","votes":8996,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accountability","votes":3029,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accounting","votes":7459,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accounts","votes":7507,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accreditation","votes":1605,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accredited","votes":3027,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accuracy","votes":6779,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accurate","votes":6427,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accurately","votes":1493,"userMade":"FALSE","limiter":"FALSE"},
{"word":"accused","votes":2853,"userMade":"FALSE","limiter":"FALSE"},
{"word":"acdbentity","votes":1389,"userMade":"FALSE","limiter":"FALSE"},
and the output would ultimately append the value paired with each word to a specific button through iteration, but also sorted by the page value.
each page is a set of buttons in a 3d object that looks like this:
the text is appended to each button which in turn is a 3d object embeded in an html object using aframe. I can make the appending code.
You can use Object.entries() to get the key value pairs of an object.
var words = [
{"word":"a","votes":9326,"userMade":"FALSE","limiter":"FALSE"},
{"word":"aaron","votes":4129,"userMade":"FALSE","limiter":"FALSE"}
];
words.forEach((wordEntry) => {
var keyValuePairs = Object.entries(wordEntry);
keyValuePairs.forEach((kv) => {
console.log(`key: ${kv[0]} value: ${kv[1]}`);
});
});
my latest attempt looks like this:
for (let p=1; p<129; p++){
for (let b=1; b<68; b++){
let pTpl = (p).toLocaleString(undefined, {minimumIntegerDigits: 3});
let bDbl = (b).toLocaleString(undefined, {minimumIntegerDigits: 2});
var `#fCont${pTpl}${bDbl}` = document.createElement('a-text');
`fCont${pTpl}${bDbl}`.setAttribute('value', 'engWordLib[p,b,0]');
`fCont${pTpl}${bDbl}`.setAttribute('votes', 'engWordLib[p,b,1]');
`fCont${pTpl}${bDbl}`.setAttribute('userMade', 'engWordLib[p,b,2]');
`fCont${pTpl}${bDbl}`.setAttribute('limiter', 'engWordLib[p,b,3]');
`fCont${pTpl}${bDbl}`.setAttribute('visible', 'false');
`fBtn${bDbl}`.appendChild(`#fCont${pTpl}${bDbl}`)
}
}
please note that I havent checked this for errors. I still think this code is to WET and I would prefer the key names for the properties be preserved in the datastructure rather than tacked on when it's appended to the page. I guess I could add a dimension to the array.... seems kind of messy when an object property value has the key value pairs right in it. cant get the iteration of objects in an array down though.... Will continue to persue a cleaner method.

jQuery parsing html into JSON

I am currently using the following code:
jQuery('#book-a-service').click(function(){
var selectedServices = jQuery('.selected').parent().parent().html();
console.log(selectedServices);
});
and that returns:
<td rowspan="3">Brakes</td>
<td class="service-title">BRAKES SET</td>
<td class="service-description"><p>Setting of front and rear brakes for proper functioning (excluding bleeding)</p></td>
<td class="service-price">R <span id="price-brakes-set">R75</span><div id="select-brakes-set" class="select-service selected"></div>
</td>
which is what i want, except i need an array of all the elements with '.selected' class in JSON.. i just want to know how i could almost parse it in a way that i only get the contents of the td tags and as for the "service-price" only the numeric value and then how would i insert those values into a json object?
Any Help Greatly Appreciated..
jQuery is not my most formidable frameworks, but this seems to do the trick.
jQuery('#book-a-service').click(function(){
var selected = jQuery('.selected');
selected.each( function() {
var children = jQuery(this).parent().parent().find('td');
var json = {};
console.log(children);
json.type = jQuery(children[0]).text();
json.title = jQuery(children[1]).text();
json.description = jQuery(children[2]).find('p').text();
json.price = jQuery(children[3]).find('span#price-brakes-set').text();
console.log(json);
console.log(JSON.stringify(json));
});
});
in action: http://jsfiddle.net/3n1gm4/DmYbb/
When various elements share the same class and you select them with $(".class"), you can iterate through all of them using:
$(".selected").each(function() {
var element = $(this); // This is the object with class "selected" being used in this iteration
var absoluteParent = $(this).parent().parent();
// Do whatever you want...
var title_element = $(".service-title", absoluteParent); // Get service-title class elements in the context provided by "absoluteParent", I mean, "inside" of absoluteParent
var title = title_element.html();
});
In the specific case of prices, I don't know exactly what is the price (probably R75?). Anyway, it should be inside a div and then select that div to obtain the price. If it is R75, then note that the "id" property should be unique for every DOM object in your HTML.
Also note that, when getting HTML, you're only getting a string, not the actual element, so it will probably not be useful for getting new values in an easy way (you won't be able to navigate through DOM elements with an ordinary string, even if it represents HTML from an actual object). Always get jQuery objects and work with them, unless you actually need the HTML.
For generating a JSON string, just create a global array and add the objects/values you need there. Then you can obtain a JSON string using var jsonText = JSON.stringify(your_array);
Consider not doing this in Javascript, as it's not useful in the majority of cases. Just send the values through POST value to a script (PHP, for example) and in the PHP you will get the actual value. The other way (PHP to Javascript) will be useful to return JSON (using json_encode($a_php_array)) and then, in Javascript, transform to a JS array using var my_array = JSON.parse(the_string_returned_by_php);.

storing table cell content into js array

I need to store table cell content into array using tr and td indexes like this:
myArray[tr_idx][td_idx]='value';
It is not required to store data of all of cells in array but only several with a special content, but if i use indexes as a keys of the array i'll have many empty array elements.
e.g.
myArray[2][3]='data1';
myArray[4][3]='data2';
alert (myArray.toSource()) -> [, , [, , , "data1"], , [, , , "data2"]]
maybe there is another suitable way of storing such type of data?
Why not just store them as individual 2-item arrays [row,col]? Since the table cells are already accessible via tableElement.rows[].cells[], you can use the 2 indices to access them from the table.
var storedCells = [];
// Store row 2, column 3
storedCells.push([2,3]);
Access with:
// Table row:
storedCells[0][0]
// Table column
storedCells[0][1]
//As in :
tableElement.rows[storedCells[0][0]].cells[storedCells[0][1]].innerHTML = "New cell value!"
Or even cleaner, if you prefer to use objects rather than arrays:
storedCells.push({row: 2, column: 3});
storedCells.push({row: 4, column: 6});
Accessed with:
tableElement.rows[storedCells[0].row].cells[storedCells[0].column].innerHTML = "New cell value!";
Finally, if you don't actually need the row/column indexes, but rather the DOM nodes themselves, just push those onto your array.
var storedCells = [];
// Save references to some individual <td> nodes
storedCells.push(tableElement.rows[1].cells[2]);
storedCells.push(tableElement.rows[4].cells[6]);
They are then trivially modified:
// Set the value of the second element:
storedCells[1].innerHTML = "New content!";
Update after comment:
If you need to be able to attach the cell coordinates to a new value from the backend, a good solution would be to expand the object {} example above to include a value attribute. The server can pass back the new value in JSON.
storedCells.push({row: 2, column: 3, value: ""});
storedCells.push({row: 4, column: 6, value: ""});
Your backend should send a JSON response back to the script containing the same type of array of objects, where value: has been populated with the new cell value. You can then pass it back into the table with:
// Pass the value attribute received from JSON into the cell's contents
tableElement.rows[storedCells[0].row].cells[storedCells[0].column].innerHTML = storedCells[0].value;
Not sure if this is the right answer but you could try to check if cells are empty before pushing them into the array. In the loop place a an if statement that will check the value of the cell and compare it to the value you require. This way you should end up with just an array of value and no empties. But you may need to record the index as well then.

How do I scan JSON with jquery to determine the number of instances of a certain string?

I have some JSON which looks generally like this...
{"appJSON": [
{
"title":"Application Title",
"category":"Business",
"industry":"Retail",
"language":"English",
"tags":[
{"tags":"Sales"},{"tags":"Reporting"},{"tags":"Transportation"},{"tags":"Hospitality"}
],
},
{
"title":"Airline Quality Assurance",
...
...
...]}
I'm looping through JSON to get an array of all of the unique Tags in the data.
My question is, now that I have an array of the different unique Tags in the JSON, how do I best determine the number of times each Tag occurs?
So basically I'm looking to generate a list of all of the tags found in the JSON (which I already have) with the number of times each one occurs (which I don't already have).
Thanks a lot in advance!
I'm assuming when you find a new tag you check to see if you already have that tag somewhere. If you don't you add it to your list. Why not when you check do something like.
var nextTag=//get the next tag in the JSON list
var newTag=true;
for(var i=0;i<tags.length;i++){
if(nextTag === tags[i]){
tagCount[i]++;
newTag=false;
break;
}
}
if(newTag){
tags[tags.length]=nextTag;
tagCount[tagCount.length]=1;
}
This uses two arrays where tagCount[i] is the number of times tag in tags[i] occurs. You could uses an object to do this or however you wanted to.
As an alternative, here's a function which will fill an associative array; the keys will be the tags and the values will be the number of occurrences of that tag.
var tagCounts = []; // Global variable here, but could be an object property or any array you like really
function countTags(tags, tagCounts)
{
$.each(tags, function(i, item) {
var tag = item.tags; // This would change depending on the format of your JSON
if(tagCounts[tag] == undefined) // If there's not an index for this tag
tagCounts[tag] = 0;
tagCounts[tag]++;
});
}
So you can call this function on any number of arrays of tags, passing in your tagCounts (totals) array, and it will aggregate the totals.
var tags1 = [{"tags":"Sales"},{"tags":"Reporting"},{"tags":"Transportation"},{"tags":"Hospitality"}];
var tags2 = [{"tags":"Reporting"},{"tags":"Transportation"}];
var tags3 = [{"tags":"Reporting"},{"tags":"Hospitality"}];
countTags(tags1, tagCounts);
countTags(tags2, tagCounts);
countTags(tags3, tagCounts);
Then you can read them out like so:
for(var t in tagCounts)
// t will be the tag, tagCounts[t] will be the number of occurrences
Working example here: http://jsfiddle.net/UVUrJ/1/
qw3n's answer is actually a more efficient way of doing things, as you're only looping through all the tags onceā€”but unless you have a really huge JSON source the difference isn't going to be noticeable.

Categories

Resources