I want to fetch the object from multi level structure
I written function for it but even on return its not coming out from function and returning value, its continue with next recursion. I know its returning value to the previously called function and as its scope is block its getting overridden and that's why returning undefined value
var selectedObj = findObjectByUid( existingStructure, selectedUid);
function findObjectByUid( root, selectedUid ) {
if( root.uniqueId === selectedUid ) {
return root;
}
if( root.children && root.children.length > 0 ) {
for( var k in root.children ) {
if( root.children[ k ].uniqueId === selectedUid ) {
return root.children[ k ];
} else if( root.children.length ) {
return findObjectByUid( root.children[ k ], selectedUid );
}
}
}
}
Here i want to get back to my initial calling function when it got matching uid.
Actually you return with the first child, regardless of the found node.
You could take a temporary variable and store the result of the children check and if not falsy return this value.
BTW, you could take the child directly of the array for the recursion.
function findObjectByUid(root, selectedUid) {
if (root.uniqueId === selectedUid) return root;
if (!root.children || !root.children.length) return;
for (let child of root.children) {
let temp = findObjectByUid(child, selectedUid);
if (temp) return temp;
}
}
var selectedObj = findObjectByUid(existingStructure, selectedUid);
There are three problems with using this approach on arrays. First, the for...in also iterates over an object's prototype properties if those properties are enumerable. For example:
Array.prototype.voice = "James Earl Jones";
var tMinus = [
"Two",
"One",
"Blast off!"
];
var countdown = "";
for (var step in tMinus) {
countdown += tMinus[step] + "\n";
}
console.log(countdown);
// => "Two
// One
// Blast Off!
// James Earl Jones
// "
That can be solved by using hasOwnProperty to exclude prototype properties.
Example:
for (var step in tMinus) {
if (tMinus.hasOwnProperty(step)) {
countdown += tMinus[step] + "\n";
}
}
Here are corrected code. You had used return findObjectByUid in inner calling by which code was terminating before completing loop.
function findObjectByUid( root, selectedUid ,foundArr) {
if( root.uniqueId === selectedUid ) {
foundArr.push(root);
return root;
}
else if( root.children && root.children.length > 0 ) {
for( var k in root.children ) {
findObjectByUid( root.children[k], selectedUid,foundArr );
if(root.children[k]=== selectedUid){break;}
}
}
return foundArr.length>0?foundArr[0]:null;
}
Sample json and calling method
var root = {uniqueId:1,children:[{uniqueId:10},{uniqueId:11,children:[{uniqueId:21,children:[]},{uniqueId:22,children:[]},{uniqueId:23,children:[{uniqueId:31,children:[]},{uniqueId:32,children:[]}]}]},{uniqueId:12,children:[]},{uniqueId:13,children:[]}]};
findObjectByUid(root,32,[]);
I have an array of objects.All these objects do not necessarily have the properties in common.
In case some of the objects from an array do have common property, I need to find their sum.
[{"taxAmount":572.26,"totalAmount":2004,"totalDiscount":0,"totalItems":12,"gTotal":2576.2599999999998,"count":4,"deployment":{"_id":"554c92f979d26026307a5a9b","name":"Punjabi Bagh"}},
{"taxAmount":304.9,"totalAmount":1111,"totalDiscount":0,"totalItems":9,"gTotal":1415.8999999999999,"count":2,"deployment{"_id":"554c930579d26026307a5a9c","name":"Pitampura"}},
{"deployment":{"_id":"554c930c79d26026307a5a9d","name":"Model Town"}},
{"deployment":{"_id":"554c945079d26026307a5cae","name":"Dwarka"}},
{"deployment":{"_id":"554cd66c0a40ccd2416e38e7","name":"Green Park"}}]
In above example, I need to add calculate individual sums of TaxAmount and totalAmount.
Also, I would need number of objects that have let's say totalAmount property.
How can I go about this in javascript?
also, is there a quick way to check if an object has any extra property except for what we have been iterating so far?
You are on the right path - reduce is one way to do it (you'll also need Object.keys to loop through each object's properties
Comments inline - note that this does a (simple) isNumber check before counting / adding
var data = [{"taxAmount":572.26,"totalAmount":2004,"totalDiscount":0,"totalItems":12,"gTotal":2576.2599999999998,"count":4,"deployment":{"_id":"554c92f979d26026307a5a9b","name":"Punjabi Bagh"}},
{"taxAmount":304.9,"totalAmount":1111,"totalDiscount":0,"totalItems":9,"gTotal":1415.8999999999999,"count":2,"deployment":{_id:"554c930579d26026307a5a9c","name":"Pitampura"}},
{"deployment":{"_id":"554c930c79d26026307a5a9d","name":"Model Town"}},
{"deployment":{"_id":"554c945079d26026307a5cae","name":"Dwarka"}},
{ "deployment": { "_id": "554cd66c0a40ccd2416e38e7", "name": "Green Park" } }]
var result = data.reduce(function (a, b) {
// loop through the properties
Object.keys(b).forEach(function (key) {
// check if it's a number
if (!isNaN(parseFloat(b[key]))) {
// get the running count / sum for this key or initialize a new one
a[key] = a[key] || { sum: 0, count: 0 }
a[key].sum += Number(b[key]);
a[key].count++;
}
})
return a;
}, {})
console.log(result)
var obj = [{"taxAmount":572.26,"totalAmount":2004,"totalDiscount":0,"totalItems":12,"gTotal":2576.2599999999998,"count":4,"deployment":{"_id":"554c92f979d26026307a5a9b","name":"Punjabi Bagh"}},
{"taxAmount":304.9,"totalAmount":1111,"totalDiscount":0,"totalItems":9,"gTotal":1415.8999999999999,"count":2,"deployment":{"_id":"554c930579d26026307a5a9c","name":"Pitampura"}},
{"deployment":{"_id":"554c930c79d26026307a5a9d","name":"Model Town"}},
{"deployment":{"_id":"554c945079d26026307a5cae","name":"Dwarka"}},
{"deployment":{"_id":"554cd66c0a40ccd2416e38e7","name":"Green Park"}}],
sumObj = { "taxAmount":0, "totalAmount":0 };
for( var o in obj ){
sumObj.taxAmount += obj[ o ].taxAmount || 0;
sumObj.totalAmount += obj[ o ].totalAmount || 0;
}
This obj[ o ].taxAmount || 0 tests if obj[ o ] has property taxAmount and if it's true-like. If it does, return it, else return 0.
Assuming your data is contained in an array called values:
var taxAmount = 0,
totalAmount = 0,
objectsWithTotalAmount = 0;
for (int i = 0; i < values.length; i++) {
if (values[i].hasOwnProperty("taxAmount") {
taxAmount += values[i].taxAmount;
}
if (values[i].hasOwnProperty("totalAmount") {
totalAmount += values[i].totalAmount;
objectsWithTotalAmount++;
}
}
With .hasOwnProperty() you check whether the object contains that property. That way you have your sums at taxAmount and totalAmount, as well as the number of objects that have the totalAmount property.
Pass in prop name to function, check every property of each array instance
var testArr = [{"taxAmount":572.26,"totalAmount":2004,"totalDiscount":0,"totalItems":12,"gTotal":2576.2599999999998,"count":4,"deployment":{"_id":"554c92f979d26026307a5a9b","name":"Punjabi Bagh"}},
{"taxAmount":304.9,"totalAmount":1111,"totalDiscount":0,"totalItems":9,"gTotal":1415.8999999999999,"count":2,"deployment":{"_id":"554c930579d26026307a5a9c","name":"Pitampura"}},
{"deployment":{"_id":"554c930c79d26026307a5a9d","name":"Model Town"}},
{"deployment":{"_id":"554c945079d26026307a5cae","name":"Dwarka"}},
{"deployment":{"_id":"554cd66c0a40ccd2416e38e7","name":"Green Park"}}];
var testTotal = getTotal('taxAmount');
alert(testTotal);
function getTotal(propName) {
var total = 0;
for (var i = 0; i < testArr.length; i++) {
for (var key in testArr[i]) {
if (testArr[i].hasOwnProperty(key)) {
if (key === propName) {
total = total + testArr[i][key];
}
}
}
}
return total;
}
Not sure what you realy want. Is it this ?
var obj = [{"taxAmount":572.26,"totalAmount":2004,"totalDiscount":0,"totalItems":12,"gTotal":2576.2599999999998,"count":4,"deployment":{"_id":"554c92f979d26026307a5a9b","name":"Punjabi Bagh"}},
{"taxAmount":304.9,"totalAmount":1111,"totalDiscount":0,"totalItems":9,"gTotal":1415.8999999999999,"count":2,"deployment":{"_id":"554c930579d26026307a5a9c","name":"Pitampura"}},
{"deployment":{"_id":"554c930c79d26026307a5a9d","name":"Model Town"}},
{"deployment":{"_id":"554c945079d26026307a5cae","name":"Dwarka"}},
{"deployment":{"_id":"554cd66c0a40ccd2416e38e7","name":"Green Park"}}],
sumObj = { "taxAmount":[], "totalAmount":[] };
for( var o in obj ){
var current = obj[ o ];
current.taxAmount && sumObj.taxAmount.push( current.taxAmount );
current.totalAmount && sumObj.totalAmount.push( current.totalAmount );
}
I'd use a recursive function, they're really easy to use in Javascript, just keep passing the same variable:
function getSumAllProps(){
var objSums = {};
var arrObjs = [{"taxAmount":572.26,"totalAmount":2004,"totalDiscount":0,"totalItems":12,"gTotal":2576.2599999999998,"count":4,"deployment":{"_id":"554c92f979d26026307a5a9b","name":"Punjabi Bagh"}},{"taxAmount":304.9,"totalAmount":1111,"totalDiscount":0,"totalItems":9,"gTotal":1415.8999999999999,"count":2,"deployment":{"_id":"554c930579d26026307a5a9c","name":"Pitampura"}},{"deployment":{"_id":"554c930c79d26026307a5a9d","name":"Model Town"}},{"deployment":{"_id":"554c945079d26026307a5cae","name":"Dwarka"}},{"deployment":{"_id":"554cd66c0a40ccd2416e38e7","name":"Green Park"}}];
for( var prop in arrObjs ){
sumProps( arrObjs[i], objSums );
}
console.log( objSums );
}
function sumProps( objIn, newObjSum ){
for( var theProp in objIn ){
if( typeof objIn[ theProp ] === 'object'){
sumProps( objIn[ theProp ], newObjSum );
}else{
if( !newObjSum[ theProp ] ) newObjSum[ theProp ] = 0;
newObjSum[ theProp ] += objIn[ theProp ];
}
}
}
You should use the Array.prototype.reduce() method. Moreover, you can do it by using the functional way and high order function.
Moreover, you can use the Arguments object in order to pass multiple parameters.
I've made a generic function in order to reduce your data.
var data = [{"taxAmount":572.26,"totalAmount":2004,"totalDiscount":0,"totalItems":12,"gTotal":2576.2599999999998,"count":4,"deployment":{"_id":"554c92f979d26026307a5a9b","name":"Punjabi Bagh"}},
{"taxAmount":304.9,"totalAmount":1111,"totalDiscount":0,"totalItems":9,"gTotal":1415.8999999999999,"count":2,"deployment":{"_id":"554c930579d26026307a5a9c","name":"Pitampura"}},
{"deployment":{"_id":"554c930c79d26026307a5a9d","name":"Model Town"}},
{"deployment":{"_id":"554c945079d26026307a5cae","name":"Dwarka"}},
{"deployment":{"_id":"554cd66c0a40ccd2416e38e7","name":"Green Park"}}];
function reducer(data, func){
//Retrieve our arguments parameter
var args = [].slice.call(arguments);
//Remove first and second element from array args
args.splice(0,2);
//Start reducing our data, initialize with an empty object
return data.reduce(function(result, current){
//ForEach key
args.forEach(function(key){
//If our object get current key, add curent value, instead of initialize it with 0
//Apply our high order function
func(result, current, key);
});
//Return our current object result
return result;
}, {});
}
//Function to sum some properties
function sum(result, current, key){
return result[key] = (result[key] || 0) + (current[key] || 0);
}
//Function to count occurence of properties
function number(result, current, key){
return current.hasOwnProperty(key)
? (result[key] = (++result[key] || 1), result)
: result
}
var res1 = reducer(data, sum, 'taxAmount', 'totalAmount');
var res2 = reducer(data, number, 'taxAmount');
So you will be able with one function to sum specific field, or count occurence, just by specifying an high order function.
After looping I got following array. Is it possible to sort this from current date to latest.
//Sortering
var arr = {};
var key = "";
var teller = 0;
for (var i = 0; i < schedule_id.length; i++) {
//Ajax call maken
$.ajax({
url: "http://api.viewer.zmags.com/schedules/" + schedule_id[i] + "?key=" + api_key
})
//WdInit after 10 calls
.done(function(data){
//Check publicatieID is not null
if (undefined === data.scheduleEntries[default_pub]|| null === data.scheduleEntries[default_pub]) {
}
else
{
var key = schedule_id[teller];
//loopen doorheen resultaat call
$.each(data.scheduleEntries, function(index, entry){
arr[key] = entry.startDate;
})
}
teller++;
})
}
arr: Object
7aaabbec: "2015-02-09T23:00:00.000Z"
31ba19e7: "2015-02-24T23:01:00.000Z"
31ff78e7: "2015-02-24T23:01:00.000Z"
159a11a7: "2015-02-10T23:01:00.000Z"
1339d0e9: "2015-02-17T23:01:00.000Z"
Code that I already got but error: Undefined is not a function
arr.sort(function(a, b) {
return a - b;
});
Objects have no order. You cannot order an object. You'd have to turn this into an array first, which in turn cannot have arbitrary keys, but is orderable.
In Javascript:
objects: key-value collections with undefined order
arrays: lists with order, but without (meaningful) keys
First get keys from object, you use something like underscore.js for this:
var keyList = _.keys( arr );
// sort keyList
keyList = keyList.sort();
// Now, do anything by getting values for sorted keys
for ( key in keyList ) {
console.log( arr[ key ] );
}
Just read your latest comment... for your case you can do it by first converting into a list of lists or list of key-val pairs
// convert into List of [ key, value ]
val pairList = _.pairs( arr );
// sort using values
pairList = pairList.sort( function( a, b ) {
// use moment.js to get date functions
var aMoment = moment( a[ 1 ] )
var bMoment = moment( b[ 1 ] )
// change based on reverse-sorted or sorted.
return bMement.diff( aMement );
} );
// Now sorted use as you want
for ( keyVal in pairList ) {
console.log( keyVal[ 0 ] + " -> " + keyVal[ 0 ] );
}
Use normal array to store the values so you can order them:
arr = [];
loopen doorheen resultaat call
$.each(data.scheduleEntries, function(index, entry){
arr.push( {'key':key, 'date':entry.startDate} );
})
arr.sort(function(a, b){
return a['date'] > b['date']; //this may need a better comparision...
});
UPDATE:
to extract the hash keys after the sorting just loop the array:
var sorted_keys = [];
for(var i = 0; i < arr.length; i++){
sorted_keys.push( arr[i] );
}
By looping object, get all dates into array and sort them and make the object again
var myObj = {
'7aaabbec': "2015-02-09T23:00:00.000Z",
'31ba19e7': "2015-02-24T23:01:00.000Z",
'31ff78e7': "2015-02-24T23:01:00.000Z",
'159a11a7': "2015-02-10T23:01:00.000Z",
'1339d0e9': "2015-02-17T23:01:00.000Z"
};
var timeArray = [], newObj = {};
for(var key in myObj){
timeArray.push([key,myObj[key]]);
}
timeArray.sort(function(a, b) {return new Date(a[1]) - new Date(b[1])});
//console.log(timeArray);
var j=0,k=1;
for(var i=0;i<timeArray.length;i++){
newObj[timeArray[i][j]] = new Date(timeArray[i][k]);
}
$("#result").html(JSON.stringify(newObj));
Working example is here
Consider this string: #page?param1=a¶m2=b¶m3=c
A hybrid application I have been working on uses window.location.hash to route the application to the right page. Often, these URLs contain parameters after the hash. Sure, this isn't standard, but it's a good solution that works nicely for our application.
I need to create a function that will take all of the parameters in the hash and return them in a object, for example: {param: value}.
I have tried other questions solution's that involve window.location.search but sadly that just returns an empty string when the parameters are after a hash.
My attempt looks like this:
return JSON.parse('{"' + decodeURI(window.location.hash).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g,'":"') + '"}');
The solution is taken from another question that uses window.location.search but using window.location.hash doesn't quite work properly, the first parameter (after the question mark) shows as undefined.
How can I create a function that would return hash parameters in an object?
The desired result for the string above would be this:
{ param1: 'a', param2: 'b', param3: 'c' }
You can use this function:
function parseParms(str) {
var pieces = str.split("&"), data = {}, i, parts;
// process each query pair
for (i = 0; i < pieces.length; i++) {
parts = pieces[i].split("=");
if (parts.length < 2) {
parts.push("");
}
data[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]);
}
return data;
}
This is taken from the .parseParms() method of a larger set of functionality on github I wrote for parsing a URL into all its pieces.
Input is a string in the form of:
"aaa=1&bbb=99&name=Bob"
and it will return an object like this:
{aaa: 1, bbb: 99, name: "Bob"}
So, if you have other things in the string besides just the parameters above, then you would need to remove those first before calling this function.
Working demo:
function parseParms(str) {
var pieces = str.split("&"), data = {}, i, parts;
// process each query pair
for (i = 0; i < pieces.length; i++) {
parts = pieces[i].split("=");
if (parts.length < 2) {
parts.push("");
}
data[decodeURIComponent(parts[0])] = decodeURIComponent(parts[1]);
}
return data;
}
console.log(parseParms("aaa=1&bbb=99&name=Bob"));
the foreEach method on arrays makes it even shorter:
const result = {};
hash.split('&').forEach(item => {
result[item.split('=')[0]] = decodeURIComponent(item.split('=')[1]);
});
function parseParms(str)
{
var pieces = str.split( "&" ),
data = {},
i, parts, key;
// Process each query pair
for ( i = 0; i < pieces.length; i++ ) {
parts = pieces[i].split( "=" );
// No value, only key
if ( parts.length < 2 ) {
parts.push( "" );
}
key = decodeURIComponent( parts[ 0 ] );
value = decodeURIComponent( parts[ 1 ] );
// Key is an array
if ( key.indexOf( "[]" ) !== -1 ) {
key = key.substring( 0, key.indexOf( "[]" ) );
// Check already there
if ( "undefined" === typeof data[ key ] ) {
data[ key ] = [];
}
data[ key ].push( value );
} else {
data[ key ] = value;
}
}
return data;
}
Working example can be found here: https://jsbin.com/xitemecuvi/edit?js,console
Hope that helps.
I've look at a few other posts but am still slightly confused about using arrays within arrays.
So I've created my array as below:
var pagesArray = [
{
category: 'pages1',
pages: [
'firstPage1',
'secondPage1',
'thirdPage1',
'fourthPage1'
]
}, {
category: 'pages2',
pages: [
'firstPage2',
'secondPage2',
'thirdPage2',
'fourthPage2'
]
}
];
Now I want to be able to search the array and find if a string exists in it. If it does, I want it to return the value of what position it is.
E.g.
jQuery.inArray('secondPage1', pagesArray)
to give the result:
pagesArray[0][1];
I'm not sure if I've written the array wrong and if I'm using inArray correctly. If I try to alert(pagesArray[0][1]); it gives a value of undefined. What am I doing wrong here?
Updated Demo
$.each(pagesArray, function (i, v) {
if((pos=$.inArray('secondPage1', pagesArray[i]['pages'])) !== -1){
console.log('pagesArray['+i+"]['pages']"+'['+pos+']');
};
});
output pagesArray[0]['pages'][1]
pagesArray[0] means found in first array [0] 0 means first
pagesArray[0]['pages'][1] found in first array [0] inside sub array ['pages'] at index [1] Second position as index starts from 0
Demo
$.each(pagesArray, function (i, v) {
if($.inArray('secondPage1', pagesArray[i]['pages']) !== -1){
alert('inarray');
};
});
to access category
console.log(pagesArray[1]['category']);
to access pages
console.log(pagesArray[1]['pages']);
to find values in array you can use
console.log($.inArray('secondPage1', pagesArray[0]['pages']));
Try this:
var pagesArray = [
{
category: 'pages1',
pages: [
'firstPage1',
'secondPage1',
'thirdPage1',
'fourthPage1' ]
}, {
category: 'pages2',
pages: [
'firstPage2',
'secondPage2',
'thirdPage2',
'fourthPage2' ]
}
];
for(var i = 0; i < pagesArray.length; i++)
{
var exist = jQuery.inArray("firstPage2", pagesArray[i]);
if(exist)
{
alert('Got the Value!!!!');
break;
}
}
Fiddle
function findInArray( arr, value ) {
var j;
for ( var i in arr ) {
if ( ~( j = arr[ i ].pages.indexOf( value ) ) )
return { i: +i, j: +j };
}
}
findInArray( pagesArray, 'thirdPage2' );
>> Object {i: 1, j: 2}
So it is pagesArray[ 1 ].pages[ 2 ]. Then:
var p = findInArray( pagesArray, 'thirdPage2' );
pagesArray[ p.i ].pages[ p.j ];
>> 'thirdPage2'
Accordingly you can write a method that returns the value or nothing to check whether an item exists:
function findInArray( arr, value ) {
var j;
for ( var i in arr ) {
if ( ~( j = arr[ i ].pages.indexOf( value ) ) )
return arr[ i ].pages[ j ];
}
return false;
}
findInArray( pagesArray, 'foo ' );
>> false
findInArray( pagesArray, 'fourthPage2' );
>> 'fourthPage2'