I need to develop a Javascript function that can convert JSON format as the following. I am not sure if there is already a javascript function for this purpose or should i develop a new one on my own
Input: (example)
{
"event[id]": "1476258193",
"event[creator]": "aziz",
"event[title]": "event[title]",
"event[review][thankyou]": "event[review][thankyou]",
"event[review][teaser]": "event[review][teaser]"
}
The Output should be something like that:
{
Events: {
Id: “1476258193”,
Creator: “aziz”
…..
Review: {
Thankyou: “”,
Teaser: “”
}
}
}
EDIT (SOLUTION) : After some work and help from other users especially "anied" i did the function myself, if some one is interested here is a plunker with the answer, the function is not 100% optimal but it does what should do
https://plnkr.co/edit/4d6cDzHXpN3RAOAJD2F0?p=preview
convert = function() {
var obj = {
"event[id]": "1476258193",
"event[creator]": "smista",
"event[title]": "event[title]",
"event[crmid]": "event[crmid]",
"event[responsible]": "event[responsible]",
"event[location]": "event[location]",
"event[ktr]": "event[ktr]",
"event[description]": "event[description]",
"event[targetgroup]": "event[targetgroup]",
"event[learninggoals]": "event[learninggoals]",
"event[status]": "offline",
"event[issuu][html]": "event[issuu][html]",
"event[group_by_threads]": "1",
"event[timeblocks][0][lectures][0][persons][0]": "2",
"event[timeblocks][0][lectures][0][persons][1]": "333333",
"event[timeblocks][0][lectures][0][persons][2]": "3",
"event[timeblocks][0][lectures][1][persons][0]": "44",
"event[timeblocks][0][lectures][1][persons][1]": "444",
"event[timeblocks][0][lectures][1][persons][2]": "4444",
"event[participants]": "event[participants]",
"event[review][thankyou]": "event[review][thankyou]",
"event[review][teaser]": "event[review][teaser]"
}
var result = "Events : {";
var mainKeyString = "" ;
var mainKeys = [] ;
var keysCount = 0 ;
for (var k in obj) {
if( obj.hasOwnProperty(k) ) {
res = k.replace('event[', '');
mainKeyString+= res ;
}
}
mainKeyString = mainKeyString.replace(/\[/g,',');
mainKeyString = mainKeyString.replace(/\]/g,',');
mainKeyString = mainKeyString.replace(/,,/g,',');
mainKeyString = mainKeyString.substring(0, mainKeyString.length-1);
mainKeys = mainKeyString.split(',') ;
for (var i in obj) {
if( obj.hasOwnProperty(i) ) {
keysCount = (i.match(/\[/g) || []).length;
var lastKey = keysCount -1 ;
for (j=0;j<keysCount;j++){
if (keysCount >1 && j != lastKey){
result += mainKeys[0] +": {";
}
else if (keysCount >1 && j == lastKey) {
result += mainKeys[0] +":\""+obj[i] + "\"}";
}
else result += mainKeys[0] +":\""+obj[i] + "\",";
mainKeys.shift() ;
}
}
}
document.getElementById("result").innerHTML = result;
}
You should develop something because I don't know that anything like that exists. You will want to write a recursive method that iterates over the object keys and adds properties to a new source object. However, one difficulty will be that you will also need to handle duplicates (of which I see a few). If you can be confident of the format of the keys (that they only contain brackets to denote new properties), then you can write something that iterates over the keys in the object using a for...in loop (for key in yourobject) and looks for substr(key.indexOf('['), key.indexOf(']') to hunt down the logical delineations. Good luck!
Related
I'm trying to know if there is a true or false reading on a substance from a dataset.
The dataset is something like this (being var drugs for l of 0),
{Caffeine: "{"drug":"Caffeine","dose":10,"amount":0}", Ritalin: "{"drug":"Ritalin","dose":"15","amount":1}"}
The algorithm i'm using in javascript is something like this currently.
var results = JSON.parse(overall[l].testdetails.result)
var drugs = overall[l].testdetails.drug
let substances = false
if (drugs != null) {
console.log("drugs: ",drugs)
for (var d = 0; d < drugs.length; d++ ){
var keyValue=Object.keys(drugs[d])
console.log("drug: ",drugs.keyValue)
if(JSON.parse(drugs.d.amount) !=0) {
substances=true
break
}
// console.log("drugs amount: ",JSON.parse(drugs[d].amount))
}
}
For some reason I am just unable to do a console log, or parse at all, this dataset.
What am i doing wrong here?
From what I can see it would be easier to iterate the drugs list if it was an array. That side, be aware if your data is a string or an object. In your code I got a bit confused about that.
String:
var drugsStr = '{"Caffeine":{"drug":"Caffeine","dose":10,"amount":0}, "Ritalin": {"drug":"Ritalin","dose":"15","amount":1}}';
var drugs = JSON.parse(drugsStr);
console.log(drugs);
Object:
var drugs = {Caffeine: {drug:"Caffeine",dose:10,"amount":0}, Ritalin: {drug:"Ritalin",dose:"15",amount:1}};
So, here is the solution with an object (drugs):
var drugs = {Caffeine: {drug:"Caffeine",dose:10,"amount":0}, Ritalin: {drug:"Ritalin",dose:"15",amount:1}};
var keys = Object.keys(drugs);
keys.forEach(key => {
console.log(drugs[key].drug);
console.log("drugs amount:", drugs[key].amount);
});
Your Json is formatted incorrectly.
let drugs = {
"Caffeine": {
"drug":"Caffeine",
"dose":10,
"amount":0
},
"Ritalin" : {
"drug":"Ritalin",
"dose":"15",
"amount":1
}
}
for (const [key, value] of Object.entries(drugs)) {
if(value['amount'] > 0 ) {
console.log( 'Positive for ' + key )
} else {
console.log( 'Negative for ' + key )
}
}
I have an array which looks like this:
["1,8", "4,6,8", "8,9", "6,9"]
1/ I would like to turn it in to this
[1,8,4,6,8,8,9,6,9]
2/ I would then like to find matching values, by looking for the most number:
[8]
This first has been solved with this:
var carArray = ["1,8", "4,6,8,7,7,7,7", "8,9", "6,9"];
//1) create single array
var arr = carArray.join().split(',');
//2) find most occurring
var counts = {}; //object to hold count for each occurence
var max = 0, maxOccurring;
arr.forEach(function(el){
var cnt = (counts[el] || 0); //previous count
counts[el] = ++cnt;
if(cnt > max && cnt > 1){ //only register if more than once (cnt>1)
max=cnt;
maxOccurring = el;
}
});
if(maxOccurring){
//there was an element more than once, maxOccuring contains that element
setResult('Most occuring: ' + maxOccurring + ' (' + max + ' times)');
}
else{
//3)/4) ???
setResult('sorting?');
}
//below is only for test display purposes
function setResult(res){
console.log(res);
}
3/ If the are no matching values like this
[1,8,4,6,5,7]
4/ Then I need to compare this array to another array, such as this
[6,7,4,1,2,8,9,5]
If the first number in <4> array above appears in <3> array, then get that number, ie in the above example I need to get 6. The <4> array will be static values and not change. The numbers is <3> will be dynamic.
EDIT Not the most elegant of answers, but I do have something working now. I didn't compare the original array directly with the second array, instead used simple if/else statements to do what I needed:
var carArray = ["1,5", "4", "8,2", "3,9,1,1,1"];
//1) create single array
var arr = carArray.join().split(',');
//2) find most occurring
var counts = {}; //object to hold count for each occurence
var max = 0, maxOccurring;
arr.forEach(function(el){
var cnt = (counts[el] || 0); //previous count
counts[el] = ++cnt;
if(cnt > max && cnt > 1){ //only register if more than once (cnt>1)
max=cnt;
maxOccurring = el;
}
});
if(maxOccurring){
//there was an element more than once, maxOccuring contains that element
console.log('Most occuring: ' + maxOccurring + ' (' + max + ' times)');
console.log(maxOccurring);
}
else {
// If not occuring, match from a list
if(jQuery.inArray("6", arr) !== -1) { console.log('6'); }
else if(jQuery.inArray("9", arr) !== -1) { console.log('9'); }
else if(jQuery.inArray("7", arr) !== -1) { console.log('7'); }
else if(jQuery.inArray("5", arr) !== -1) { console.log('5'); }
else if(jQuery.inArray("4", arr) !== -1) { console.log('4'); }
else if(jQuery.inArray("1", arr) !== -1) { console.log('1'); }
else { console.log('not found'); }
}
Example Fiddle
Step 1 is fairly easy by using javascript's join and split methods respectively:
var arr = carArray .join().split(',');
For step 2, several methods can be used, the most common one using an object and using the elements themselves as properties. Since you only need to get the most occurring value if there is a reoccurring value, it can be used in the same loop:
var counts = {}; //object to hold count for each occurence
var max = 0, maxOccurring;
arr.forEach(function(el){
var cnt = (counts[el] || 0); //previous count
counts[el] = ++cnt;
if(cnt > max && cnt > 1){ //only register if more than once (cnt>1)
max=cnt;
maxOccurring = el;
}
});
After the above, the variable maxOccurring will contain the reoccurring value (if any) and max will contain the times it occured
For step 4 the easiest way is to loop through the compare array and get the element that occurs in the input array:
var cmpArr = ['6','7','4','1','2','8','9','5'];
//find the first occurrence inside the cmpArr
res = function(){ for(var i= 0 ; i < cmpArr.length; i++){ if(arr.indexOf(cmpArr[i]) !== -1)return cmpArr[i];}}();
The above uses an in place function which is called immediately to be able to use return. You could also just use a loop and assign res when found, then break from the loop.
Last update, an alternate fiddle where the above is converted to a single function: http://jsfiddle.net/v9hhsdny/5/
Well first of all the following code results in four matching answers since the jQuery selectors are the same.
var questionAnswer1 = $(this).find('input[name=questionText]').val();
var questionAnswer2 = $(this).find('input[name=questionText]').val();
var questionAnswer3 = $(this).find('input[name=questionText]').val();
var questionAnswer4 = $(this).find('input[name=questionText]').val();
var carArray = [questionAnswer1, questionAnswer2, questionAnswer3, questionAnswer4];
You could use the eq(index) method of jQuery to select the appropriate element. However having 4 inputs with the same name is a bad practice.
Well lets say that the carArray has 4 different values which all consist out of comma separated numbers. You could then do the following:
var newArr = [];
carArray.forEach(function(e) {
e.split(",").forEach(function(n) {
newArr.push(n);
});
});
Well then we got to find the most occurring number. JavaScript doesn't have any functions for that so we will have to find an algorithm for that. I found the following algorithm on this stackoverflow page
var count = function(ary, classifier) {
return ary.reduce(function(counter, item) {
var p = (classifier || String)(item);
counter[p] = counter.hasOwnProperty(p) ? counter[p] + 1 : 1;
return counter;
}, {})
}
var occurances = count(newArr);
It isn't clear to me what you're trying to do in step 3 and 4, so can't answer those at the moment.
var ary = ["1,8", "4,6,8", "8,9", "6,9"];
var splitted = ary.reduce(function(acc, item) {
return acc.concat(item.split(','));
}, []);
var occurences = splitted.reduce(function(acc, item) {
if (!acc.hasOwnProperty(item)) acc[item] = 0;
acc[item] += 1;
return acc;
},{}),
biggest = Object.keys(occurences).reduce(function (acc, key) {
if (occurences[key] > acc.occurences) {
acc.name = key;
acc.occurences = occurences[key];
}
return acc;
},{'name':'none','occurences':0}).name;
var vals=["1,8", "4,6,8", "8,9", "6,9"];
// 1) turn into number array
var arrNew=[];
for(var i=0; i<vals.length; i++)
{
arrLine=vals[i].split(",");
for (var j=0;j<arrLine.length;j++) { arrNew.push (parseInt(arrLine[j])) }
}
//result:
alert(arrNew.join(";");
// 2) find most common
var found=[];
for(var i=0; i<arrNew.length; i++) {
// make an array of the number of occurrances of each value
if (found["num"+newArray[i]]) {
found["num"+newArray[i]] ++ ;
} else {
found["num"+newArray[i]]=1;
}
}
var mostCommon={count:0,val:"ROGUE"};
for (x in found) {
if (found[x] > mostCommon.count) {
mostCommon.count=found[x].count;
mostCommon.val=x;
}
}
// result :
alert(mostCommon.val);
//3) not quite sure what you meant there
// 4) unique values:
// at this point the 'found' list contains unique vals
var arrUnique=[];
for (x in found) {
arrUnique.push[x];
}
// result :
alert(arrUnique.join(";"))
//sort:
arrUnique.sort(function(a, b){return a-b});
(This won't work in most browsers) but on a side note, when ES6 becomes widely supported, your solution could look like this:
var arr1 = ["1,8", "4,6,8", "8,9", "6,9"];
var arr2 = arr1.join().split(',');
var s = Array.from(new Set(arr2)); //Array populated by unique values, ["1", "8", "4", "6", "9"]
Thought you might like to see a glimpse of the future!
1.
var orgArray = ['1,8', '4,6,8', '8,9', '6,9'];
var newArray = [];
for (var i in orgArray) {
var tmpArray = orgArray[i].split(',');
for (var j in tmpArray) {
newArray.push(Number(tmpArray[j]));
}
}
2.
var counts = {};
var most = null;
for (var i in newArray) {
var num = newArray[i];
if (typeof counts[num] === 'undefined') {
counts[num] = 1;
} else {
++(counts[num]);
}
if (most == null || counts[num] > counts[most]) {
most = num;
} else if (most != null && counts[num] === counts[most]) {
most = null;
}
}
I don't understand the question 3 and 4 (what "unique order" means) so I can't answer those questions.
Folks, using js libraries such as underscore,underscore.string, or lodash, I'd like to convert the following String to an Object
'animals=cat&dogs&horses&fish=salmon&tuna';
The following are constant: animals and fish. Separator is =
The result should look like:
{
animals: 'cats&dogs&horses',
fish: 'salmon&tona'
}
animals and fish can occur in the string in any order.
Thanks!
PS Its not a duplicate of Parse query string in JavaScript... as the requirements are to return an object for later parsing...
Quick vanilla js solution:
function parseQuery (string) {
var result = {}, components, i, firstPair, current;
components = string.split("&");
for (i = 0; i < components.length; i++) {
if (components[i].indexOf("=") !== -1) {
if (typeof current !== "undefined") {
result[current] = result[current].join("&");
}
firstPair = components[i].split("=");
current = firstPair[0];
result[current] = [firstPair[1]];
} else {
result[current].push(components[i]);
}
}
result[current] = result[current].join("&");
return result;
}
This is a bit more compact:
var x = 'animals=cat&dogs&horses&fish=salmon&tuna';
Split the string using the feature of split which preserves splitters which are groups in the splitting regexp. We split on anything which starts at the beginning of the string or with a &, and contains an = at the end:
var pieces = x.split(/((?:^|&)\w+=)/) . filter(Boolean);
>> ["animals=", "cat&dogs&horses", "&fish=", "salmon&tuna"]
The result will be an array of interspersed keynames and values. Process this into an object:
var result = {};
for (var i=0; i<pieces.length; i+=2) {
result[pieces[i].replace(/^&|=$/g, '')] = pieces[i+1];
}
Basically, I have a multidimensional array that I need to build into a simple string.
Quite an easy question, although it has been eating away at me for quite some time now since I can't seem to nail it.
Here is an example of how my array could look with just 3 questions within it:
[["question1","answer1","answer2","answer3","answer4"],["question2","answer1","answer2","answer3","answer4"],["question3","answer1","answer2","answer3","answer4"]]
For example, D.rows[0][0] would be "question1" and D.rows[2][3] would be "answer3", just to clarify.
Here is how it must be saved into a string as:
question1,answer1,answer2,answer3,answer4
question2,answer1,answer2,answer3,answer4
question3,answer1,answer2,answer3,answer4
Each element must have a comma between them, and each question must be separated by a line-break.
This is what I currently have that is not working:
var fullString;
for (i = 0; i < csvArray.length; ++i)
{
second = secondArray[i];
for (j = 0; j < second.length; ++j)
{
fullString += entry[j] + "'";
}
fullString += "\n";
}
Thanks in advance!
try this
var s,a=[["question1","answer1","answer2","answer3","answer4"],"question2","answer1","answer2","answer3","answer4"],["question3","answer1","answer2","answer3","answer4"]];
for(i=0; i < a.length; i++){
s=(s)?s+"\n\r"+a[i].join():a[i].join();
}
jsfiddle example
In your own example: since you are going straight to adding to fullString, it should have an empty string for value, otherwise you will end up with undefined in the beginning.
var fullString="";
this part second = secondArray[i]; should have been
var second = csvArray[i];
and in a same way this fullString += entry[j] + "'"; should have been
fullString += second[j] + ",";
one liner:
var result = [["question1","answer1","answer2","answer3","answer4"],["question2","answer1","answer2","answer3","answer4"],["question3","answer1","answer2","answer3","answer4"]].join('\r\n');
something like this:
var questionAnswerSet= { "question1" : [
{ "answer1" : "value",
"answer2" : "value",
"answer3" : value}
],
"question2" : [
{ "answer1" : "value",
"answer2" : "value",
"answer3" : value}
],
}
and access like this:
questionAnswerSet[0].answer2 // question one answer 2
questionAnswerSet[1].answer2 // question two answer 2
for (var i=0; i<yourArray.length; i++) { // iterate on the array
var obj = yourArray[i];
for (var key in obj) { // iterate on object properties
var value = obj[key];
console.log(value);
}
}
If you have an array as this...
var arr = [["question1","answer1","answer2","answer3","answer4"],["question2","answer1","answer2","answer3","answer4"],["question3","answer1","answer2","answer3","answer4"]];
then...
var strArr = arr.join(',');
var strLine = arr.join('\n'); // string with line breaks.
will do that for you.
if you want different strings for each question-answer block, then...
var strJoinArr = [], strJoinLines = '';
for(var i = 0; i < arr.length; i++){
strJoinArr.push(arr[i].join(','));
strJoinLines += arr[i].join(',')+ '\n'; // string with line break
}
then to access each section you can use indexes,
For example, strJoinArr[2] will return 'question3,answer1,answer2,answer3,answer4'
more on .join()
more on .push()
This might be your solution if you plan ot change separators or number of answers.
var array = [["question1","answer1","answer2","answer3","answer4"],["question2","answer1","answer2","answer3","answer4"],["question3","answer1","answer2","answer3","answer4"]],
string = "";
for (var i = 0; i <= array.length - 1; i++) {
string +=array[i].join(', ');
string += "\n";
}
Also, in the less readable but also effective way, for any object of this structure
string = array.join('\r\n');
I have a string that looks something like the following 'test:1;hello:five;just:23'. With this string I need to be able to do the following.
....
var test = MergeTokens('test:1;hello:five;just:23', 'yes:23;test:567');
...
The end result should be 'test:567;hello:five;just:23;yes:23' (note the exact order of the tokens is not that important).
Just wondering if anyone has any smart ideas of how to go about this. I was thinking a regex replace on each of the tokens on right and if a replace didn't occur because there was not match just append it. But maybe there is better way.
Cheers
Anthony
Edit: The right side should override the left. The left being what was originally there and the right side being the new content. Another way of looking at it, is that you only keep the tokens on the left if they don't exist on the right and you keep all the tokens on the right.
#Ferdinand
Thanks for the reply. The problem is the efficiency with which the solution you proposed. I was initially thinking down similar lines but discounted it due to the O(n*z) complexity of the merge (where n and z is the number tokens on the left and right respectively) let alone the splitting and joining.
Hence why I was trying to look down the path of a regex. Maybe behind the scenes, regex is just as bad or worse, but having a regex which removes any token from the left string that exists on the right (O(n) for the total amount of token on the right) and then just add the 2 string together (i.e. vat test = test1 + test2) seems more efficient. thanks
I would use join() and split() to create some utility functions to pack and unpack your token data to an object:
// Unpacks a token string into an object.
function splitTokens(str) {
var data = {}, pairs = str.split(';');
for (var i = 0; i < pairs.length; ++i) {
var pair = pairs[i].split(':');
data[pair[0]] = pair[1];
}
return data;
}
// Packs an object into a token string.
function joinTokens(data) {
var pairs = [];
for (var key in data) {
pairs.push(key + ":" + data[key]);
}
return pairs.join(';');
}
Using these, merging is easy:
// Merges all token strings (supports a variable number of arguments).
function mergeTokens() {
var data = {};
for (var i = 0; i < arguments.length; ++i) {
var d = splitTokens(arguments[i]);
for (var key in d) {
data[key] = d[key];
}
}
return joinTokens(data);
}
The utility functions are also useful if you want to extract some keys (say,"test") and/or check for existence:
var data = splitTokens(str);
if (data["test"] === undefined) {
// Does not exist
} else {
alert("Value of 'test': " + data["test"]);
}
The following is what I ended thiking about. What do you guys recon?
Thanks
Anthony
function Tokenizer(input, tokenSpacer, tokenValueSpacer) {
this.Tokenizer = {};
this.TokenSpacer = tokenSpacer;
this.TokenValueSpacer = tokenValueSpacer;
if (input) {
var TokenizerParts = input.split(this.TokenSpacer);
var i, nv;
for (i = 0; i < TokenizerParts.length; i++) {
nv = TokenizerParts[i].split(this.TokenValueSpacer);
this.Tokenizer[nv[0]] = nv[1];
}
}
}
Tokenizer.prototype.add = function(name, value) {
if (arguments.length == 1 && arguments[0].constructor == Object) {
this.addMany(arguments[0]);
return;
}
this.Tokenizer[name] = value;
}
Tokenizer.prototype.addMany = function(newValues) {
for (nv in newValues) {
this.Tokenizer[nv] = newValues[nv];
}
}
Tokenizer.prototype.remove = function(name) {
if (arguments.length == 1 && arguments[0].constructor == Array) {
this.removeMany(arguments[0]);
return;
}
delete this.Tokenizer[name];
}
Tokenizer.prototype.removeMany = function(deleteNames) {
var i;
for (i = 0; i < deleteNames.length; i++) {
delete this.Tokenizer[deleteNames[i]];
}
}
Tokenizer.prototype.MergeTokenizers = function(newTokenizer) {
this.addMany(newTokenizer.Tokenizer);
}
Tokenizer.prototype.getTokenString = function() {
var nv, q = [];
for (nv in this.Tokenizer) {
q[q.length] = nv + this.TokenValueSpacer + this.Tokenizer[nv];
}
return q.join(this.TokenSpacer);
}
Tokenizer.prototype.toString = Tokenizer.prototype.getTokenString;
i am a few years late, but i think this is what you are looking for:
function MergeTokens(input, replace){
var replaceTokens = replace.split(";");
for(i=0; i<replaceTokens.length; i++){
var pair = replaceTokens[i].split(":");
var result = input;
regString = "\\b" + pair[0] + ":[\\w]*\\b";
var reg = new RegExp(regString);
if(reg.test(result)){
result = result.replace(reg, replaceTokens[i]);
}
else{
result = result + replaceTokens[i];
}
}
return result;
}