What javascript techniques are used in this array parser? - javascript

I have the following script that dumps a given array's contents
function dump(obj) {
obj = obj || {};
var result = [];
$.each(obj, function (key, value) { result.push('"' + key + '":"' + value + '"'); });
return '{' + result.join(',') + '}';
}
... but I don't understand the "array" functions of this. Can you tell me what I need to learn to comprehend what is going within the .each statement?
Update
e.values below is an example of what obj looks like.

This is using jQuery for the each http://api.jquery.com/jQuery.each/ to do the iterating. Here is what happens in your dump function:
function dump(obj) {
// If 'obj' is falsy then make 'obj' a new Object
obj = obj || {};
// Create a new Array
var result = [];
// Loop over each property in 'obj' and add
// "key":"val" String to the 'result' Array,
$.each(obj, function (key, value) { result.push('"' + key + '":"' + value + '"'); });
// Join the Array using "," as the delimiter and wrap
// this with { ... }. Example of arr.join():
// var arr = [1, 2, 3];
// console.log(arr.join(".")); // "1.2.3"
// console.log(arr.join("|")); // "1|2|3"
return '{' + result.join(',') + '}';
}
Edit
If you need to get the key(s) of an arbitrary Object you can use:
function getKeys(obj) {
var keys = [],
i;
for (var i in obj) {
if (obj.hasOwnProperty(i)) {
keys.push(i);
}
}
return keys;
}
var keys = getKeys({key: "value"}); // ["key"]
Here's a working example.
You could also have a look at Underscore.js's _.keys().

Basically all that code is doing is creating a string version of the object.
Demo: http://jsfiddle.net/GYJAT/
The $.each is a jQuery function that goes through the array.

Based on the comments you left, it seems that your main question is about how to get the keys of an object.
First, in your code sample jQuery does it automatically for you as part of the each function:
$.each(obj, function (key, value) ...
If you need to do it yourself, modern browsers have the keys property: Object.keys(obj)
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/keys
With older browsers, you'll need to use a for loop (note the HasOwnProperty test):
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/HasOwnProperty#Example:_Iterating_over_the_properties_of_an_object

Related

JS access an array with in an object

I have a variable holding a string of validated JSON. The JSON is a set of strings each with a value of an array. I'd like to access the string and each array value.
var json_string = {"div-1":["div-1A", "div-1B"], "div-2":["div-2A", "div-2B"]};
//Run some code to get the following result:
console.log("div-1" has "div-1A");
console.log("div-1" has "div-1B");
console.log("div-2" has "div-2A");
console.log("div-2" has "div-2B");
I have tried a bunch of different things but nothing seems to work right. Additionally, I get a weird functionality. If I do the following:
console.log(json_string["div-1"]);
I randomly get the following results for each page refresh :
div-1A //initial load
div-1C //refresh 1
div-1A //refresh 2
div-1B //etc
div-1A //etc
Any ideas how I can get what I am after?
You can first retrieve the values from keys and then use forEach to get their value
var json_string = {"div-1":["div-1A", "div-1B"],
"div-2":["div-2A", "div-2B"]
};
for(var key in json_string){
var _getValue = json_string[key]
if(_getValue.constructor===Array){ // Checking if it is an array
_getValue.forEach(function(item){
document.write('<pre>'+item+'</pre>')
})
}
JSFIDDLE
It'll be something like this if I understand correctly. You have to traverse through each property and take the array property value against that key.
for (key in json_string) {
var arr = json_string[key];
arr.forEach(function(item) {
console.log(key + ' has ' + item);
});
}
Use Object.keys() for getting all object keys and Array#forEach for iterating over array.
var json_string = {
"div-1": ["div-1A", "div-1B"],
"div-2": ["div-2A", "div-2B"]
};
// Get all object keys and iterate over them
Object.keys(json_string).forEach(function(key) {
// Get inner array using key and iterate
json_string[key].forEach(function(el) {
console.log(key + ' has ' + el)
});
});
For older browser check polyfill option for Object.keys method and forEach method.
It looks like your json_string is actually a JSON object (there's a difference). That said, keys within an object do not follow any sort/ordering. You will need to sort your keys before your output:
var obj = {
"div-1": ["div-1A", "div-1B"],
"div-2": ["div-2A", "div-2B"]
};
Object.keys( obj ).sort().forEach( key =>
obj[ key ].sort().forEach( val =>
console.log( [key,'has',val].join(' ') )
)
);
Of course you could also write your own function to output values for a specific key. Below adds a prototype function to Object, which is just an example (prototyping is generally not recommended):
Object.prototype.valuesFor = function(key){
this[key].sort().forEach( val =>
console.log( [key,'has',val].join(' ') )
)
return this[key];
};
var obj = {
"div-1": ["div-1A", "div-1B"],
"div-2": ["div-2A", "div-2B"]
};
obj.valuesFor('div-1')

What is the simplest way to Join a object as a space separated string in Javascript

All:
I want to build a string from a JS object( like build a toString method but like operator overload), for example:
var info = {name:"username",age:20};
var fmtinfo = info.join("||");
the fmtinfo will be a string with format:
"name(username)||age(20)"
I wonder if anyone can give me a simple way to do that?
Thanks
To avoid any explicit iteration, you can use Object.keys with map to transform each key into the corresponding entry, then simply join them together:
function fancyString(obj) {
return Object.keys(obj).map(function (k) {
return "" + k + "(" + obj[k] + ")";
}).join("||");
}
var foo = {name: "username", age: 20};
console.log(fancyString(foo));
To offer some explanation of how this work:
The call to Object.keys() returns an array of the object's own enumerable keys, effectively combining the for (f in o) and o.hasOwnProperty() checks. Object.keys is relatively well-supported, by everything except IE9 (although polyfills are not complicated).
That array of keys are transformed via Array.prototype.map(), using the desired string formatting. This is pretty simple, but do not that obj[k] will call its .toString() method (if available) to transform it into a string. This allows excellent handling of custom objects, as you can simply define a toString method on each and it will be picked up by the VM. Again, this is supported by IE9 and better, but polyfills are trivial.
Finally, we join the resulting strings with Array.prototype.join(), which takes care of making sure we don't append the separator to the end or anything like that. All browsers support this.
For curiosity, the ES6 equivalent would be:
let fancyString = o => Object.keys(o).map(k => "" + k + "(" + o[k] + ")").join("||");
You can use for..in statement and helper array:
var info = {name:"username",age:20};
var helperArray = [];
for( var key in info ) {
if( info.hasOwnProperty( key ) ) {
helperArray.push( key + '(' + info[key] + ')' );
}
}
alert(helperArray.join('||'));
You could iterate over the object's keys to get both the key names and their corresponding values. Not incredibly elegant but since the desired format of your string is uncommon, it requires a little work.
var info = {name:"username",age:20};
var keys = Object.keys(info);
var returnVal = ""
for(var i = 0; i < keys.length; i++) {
if(returnVal.length > 0)
returnVal += "||";
returnVal += keys[i] + "(" + info[keys[i]] + ")";
}
alert(returnVal)
Here is a jsfiddle of the solution: http://jsfiddle.net/pstricker/ec1oohsk/
It took a while, but I might have got it working as intended with help of two existing Stackoverflow answers related to: Object iteration and checking if JavaScript variable is function type. I hope this helps :-)
Object.prototype.join = function join(param) {
var helperArray = []
for (var key in this) {
//check that function is not printed -> join: function
if (typeof (this[key]) != "function")
helperArray.push(key + "(" + this[key] + ")")
}
return helperArray.join(param);
}
var info = {
name: "username",
age: 20
};
console.log(info.join('||'));
console.log(info.join('<>'));
console.log(info.join('%'));
Object.prototype.fancyString = function(){
var a = []
for(var prop in this) {
if(this.hasOwnProperty(prop)) {
a.push(prop + '(' + this[prop] + ')' );
}
}
return a.join('||');
}
Then you can just do:
var info = {name:"username",age:20};
info.fancyString();
// outputs: "name(username)||age(20)"

A javascript class that takes a JSON object and converts it into an attribute property

I tried to convert a JSON object into an attribute string in javascript.
Like:
json = {a:"1", b:"2"};
and the output will be html elements, like
"< div a='1', b='2'>< /div>"
I tried in this way,
var json = {a:"1", b:{c:"2", d:"3"}};
function myFunction(obj, json) {
for (var i in json) {
obj[i] = json[i];
}
}
As far i know the obj is created but I failed to make the proper output which can be used in the html, because the json object can be nested. Sorry again for this noob question.
Well, i write something like this:
var o = {a:"1", b:{c:"2", d:"3"}}
function objToString (obj) {
var str = '<div ';
for (var p in obj) {
if (obj.hasOwnProperty(p)) {
str += p + '=' + '"'+obj[p]+'"' + ',';
}
}
str= str.replace(/,$/ , '>');
return str;
}
objToString (o);
But the above code not working for nested object. So, i tried this way:
var o = {
a: "1",
b: {
c: "2",
d: "3"
}
}
console.log(o);
var tx = new String();
tx = '<div ' + JSON.stringify(o) + '>';
console.log(tx);
tx.replace(/:/gi, '=');
tx = tx.replace(/}/, '');
tx = tx.replace(/{/, '');
console.log(tx);
But this time the output not match for proper html... Haven save me :(
I programmed something that should deal with your problem. If I understood you right, this is exactly what you need.
I solved this problem using recursion and the visitor pattern. Works like a charm.
I didn't test it for all possible types but missing types can be inserted easily when needed.
Arrays do crash currently - you will need to catch this if they appear too.
Some explanation:
1) I tested the types of the values.
2) I initialized an array that store values I could find.
3) I wrote a recursive method that tests object-properties for being objects
4) If the property is a object it will be used recursively in the same method.
5) If the property is no object, it's data will be added to the previously initialized array.
6) After the recursive method's executing I debug the array and create a sample output.
// the object to use:
var o = {a:1, b:{c:"2", d:"3"}}
// some type testing:
//alert(typeof(o.a)); // string
//alert(typeof(o.b)); // object
// implement a recursive method that reads all
// the needed stuff into a better-to-handle array.
function readAttributesRecursive(obj, arr) {
for(prop in obj) {
// get the value of the current property.
var propertyValue = obj[prop];
// get the value's type
var propertyValueType = typeof(propertyValue);
// if it is no object, it is string, int or boolean.
if(propertyValueType !== 'object') {
arr.push({
property : prop,
value : propertyValue,
type : propertyValueType // just for debugging purposes
});
}
// otherwise it is a object or array. (I didn't test arrays!)
// these types are iterated too.
else {
// red the object and pass the array which shall
// be filled with values.
readAttributesRecursive(propertyValue, arr);
}
}
} // END readAttributesRecursive(obj, arr)
// ok, lets get the values:
var result = new Array();
readAttributesRecursive(o, result)
console.debug(result);
// the result looks like this:
// [
// { property : "a", type : "number", value: "1" }
// { property : "c", type : "string", value: "2" }
// { property : "d", type : "string", value: "3" }
// ]
// And now do the <div>-stuff:
var div = '<div';
for(i = 0; i < result.length; i++) {
var data = result[i];
div += ' ' + data.property + '="' + data.value + '"';
}
div += ">Some text</div>";
console.debug(div);
Note:
Please do never create HTML-elements like this (using strings)!
Use document.createElement() and work with created DOM-elements. Using strings can result in strange behaviour , bugs and less readable code ... (strings are not EXACTLY treated like DOM-elements after being inserted into DOM)
Are you just looking for jQuery's .attr()? You can create an element, add a few attributes and text and append it to the body like this:
$('<div/>')
.attr({
"class":"some-class",
"id":"some-id",
"data-fancy": "fancy pants"
})
.text('Hello World')
.appendTo('body');

Parsing JSON using javascript only

I tried looking for a similar question, couldn't find anything detailed enough.
I have a an ajax call, which calls a php page and the response is:
echo json_encode($cUrl_c->temp_results);
Which outputs:
{"key":"value", "key2":"value"}
The output is being "parsed" using:
var json_response = JSON.parse(xmlhttp.responseText);
I was looking for a way to iterate through the response, and getting
the key and value using javascript only.
is the returned output considered valid json ?
How do I loop through it (no jquery just javascript) ?
To iterate through the items of an object, you normally use a for..in loop, which let you access the keys (property names) as well as the property values:
for (var key in object) {
var item = object[key];
}
And yes, {"key":"value", "key2":"value"} is valid JSON.
To answer your first question, yes it is considered valid JSON once you parse it with JSON.parse(), as you have. To answer your second question, have a look at for...in from the MDN.
You could use the first example in the doc to find out how to get the keys and values.
Example 1
var o = {a:1, b:2, c:3};
function show_props(obj, objName) {
var result = "";
for (var prop in obj) {
result += objName + "." + prop + " = " + obj[prop] + "\n";
}
return result;
}
alert(show_props(o, "o")); /* alerts: o.a = 1 o.b = 2 o.c = 3 */

Best way of basically doing a `where` clause in Javascript?

I'm trying to parse some JSON that is sent to me and it's all in the format of
[{key:value},{key2:value2}, ... ]
What would be the best way to get the value of key2 in this? Is there a way to do it without doing a for loop?
You could use the Select function from the Underscore.js library.
Not really, but it wouldn't be hard to create a function to do that. However, it would indeed involves a for loop.
For the sake of completion, that would be the function:
function selectWhere(data, propertyName) {
for (var i = 0; i < data.length; i++) {
if (data[i][propertyName] !== null) return data[i][propertyName];
}
return null;
}
Usage:
var key2value = selectWhere(data, "key2");
Javascript Array comes with methods that do just what you are asking for - find entries without you having to code a for-loop.
You provide them with the condition that you want. A compact and convenient way to do that is with an arrow (or "lambda") function. In your case, you are looking for array entries that have a specific key, so the arrow function could look something like this:
e => e.hasOwnProperty("key2")
Following the lead of some of the others, let's start with the assumption
var arr = [{key:"value"}, {key2:"value2"}, {key3:"value3"}]
If you expect that at most one member of the array has the key you want, you can use the find() function. It will test each array member until it finds one where your condition is true, and return it. If none are true, you'll get undefined.
var foundentry = arr.find(e => e.hasOwnProperty("key2"))
Either foundentry will be undefined or it will be the {key2:"value2"} that you are looking for, and can extract value2 from it.
If arr can have more than one entry with the key that you are looking for, then instead of find() use filter(). It gives back an array of entries that meet your criteria.
var foundarray = arr.filter(e => e.hasOwnProperty("key2"))
jQuery grep() is a good analog for a Where clause:
var array = [{key:1},{key:2}, {key:3}, {key:4}, {key:5}];
var filtered = jQuery.grep(array, function( item, index ) {
return ( item.key !== 4 && index > 1 );
});
Your filtered array will then contain two elements,
[{key:3}, {key:5}]
You can't do it with an array, but you can make an associative array like object with it. Once you make it, you can use it like hash.
var arr = [{key:value},{key2:value2}, ... ], obj = {};
for (var i = 0, len = arr.length; i < len; i++) {
$.extend(obj, arr[i]);
}
console.log(obj.key2); // value2
Here's an example that prototype's the Array object. Note: this is shown for example - find is not a good name for this function, and this probably will not be needed for all arrays
Instead, consider just using the function definition and creating a function like getObjVal, calling like getObjVal(arr,'propName'), similar to LaurenT's answer.
Given
var arr = [{key:'value'},{key2:'value2'}];
Definition
// for-loop example
Array.prototype.find = function (prop){
for(var i=this.length; i--; )
if (typeof this[i][prop] !== 'undefined')
return this[i][prop];
return undefined;
}
// for-each loop example
Array.prototype.find = function (prop){
for (var i in this)
if ( this.hasOwnProperty(i) && typeof this[i][prop] !== "undefined" )
return this[i][prop];
return undefined;
}
Usage
console.log( arr.find('key2') ); // 'value2'
console.log( arr.find('key3') ); // undefined
Use .filter() method for this object array, for example in your case:
var objArray = [{key:"Hello"},{key2:"Welcome"} ];
var key2Value=objArray.filter(x=>x.key2)[0].key2;
Regex - no for loop:
var key2Val = jsonString.match(/\{key2:[^\}]+(?=\})/)[0].substring("{key2:".length);
Top answer does the job. Here's a one liner version of it using lodash (same as underscore for the most part):
var result = _.filter(data, _.partialRight(_.has, 'key2'));
In lodash, select is just an alias for filter. I pass it the data array filled with objects. I use _.has as the the filter function since it does exactly what we want: check if a property exists.
_.has expects two args:
_.has(object, path)
Since _.has expects two arguments, and I know one of them is always constant (the path argument). I use the _.partialRight function to append the constant key2. _.partialRight returns a new function that expects one argument: the object to inspect. The new function checks if obj.key2 exists.
Heyas. You can use the lodash library's .reduce() or .transform() functions to implement this. Lodash is more modular than underscore (Underscore around 5kb, Lodash around 17kb), but is generally lighter because you only include the specific modules you need
(please see: https://news.ycombinator.com/item?id=9078590 for discussion). For this demonstration I will import the entire module (generally not an issue on the backend):
I wrote these snippets for either scenario which handle both numeric and non-numeric arguments.
https://lodash.com/docs#reduce
https://lodash.com/docs#transform
Pull in lodash:
var _ = require('lodash');
_.reduce() to where clause:
var delim = ' WHERE ', where = _.isEmpty(options) ? '' : _.reduce(options, function(r, v, k) {
var w = r + delim + k + '=' + (_.isNumber(v) ? v : ("'" + v + "'"));
delim = ' AND ';
return w;
}, '');
_.transform() to where clause:
var where = _.isEmpty(options) ? '' : ' WHERE ', delim = '';
_.transform(options, function(r, v, k) {
where = where + delim + k + '=' + (_.isNumber(v) ? v : ("'" + v + "'"));
delim = ' AND ';
});
Hope that helps.
Try this:
var parsedJSON = JSON.parse(stringJSON);
var value = parsedJSON['key2'];

Categories

Resources