how to recursively loop inside object - javascript

How to get all the values of the object and compare
Object :
obj = {
a : 10,
b : [{b1 : 101 , b2:201},{b3 : 102 , b4:204}],
c : [{c1 : 107 , c2:209 ,d :[{d1:109},{d2:402}]}]
}
function compareValues(101,obj) {
if (retriveValueFromObject(obj,101)) {
return true;
} else {
return false;
}
function comparator(a, b) {
return ('' + a).toLowerCase().indexOf(('' + b).toLowerCase()) > -1;
}
}
Pending :
retriveValueFromObject() need to be implemented such a way that i will loop in to all the key value pair of the object and send back flag(t/f) if value is in the object.

You could try something like this:
function retriveValueFromObject(theObject, value) {
for(var prop in theObject) {
if(theObject[prop] == value) {
return true;
}
if(theObject[prop] instanceof Object || theObject[prop] instanceof Array)
return getObject(theObject[prop]);
}
return false;
}
I found this here : https://stackoverflow.com/a/15524326/1062711

try:
function retrieveValueFromObject(obj,101) {
var result;
for (var key in obj){
if (typeof(obj[key]) !== 'Object')
result = comperator(101, obj[key]);
else
result = retrieveValueFromObject(obj[key],101);
}
return result;
}
didn't get to test it myself, though.

I would suggest to retrieve all values from object recursively into array and then check with Array.prototype.indexOf():
function getValues(obj) {
var result = [];
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
var curVal = obj[key];
if (typeof (curVal) === 'object') {
result = result.concat(getValues(curVal));
} else {
result.push(curVal);
}
}
}
return result;
}
console.log(getValues(o));
console.log(getValues(o).indexOf(101) !== -1);
console.log(getValues(o).indexOf('nosuchvalue') !== -1);
Fiddle

Related

Clear a variable counter inside forEach loop?

I'm trying to reset a (file public) counter that is used inside a recursive forEach loop.
Basically the code below checks the length of the innermost key-value pair where:
length = (key length) + (some strings inserted) + (key value)
var container = ''
var length = 0
function getUpdatedLengthOfInnerMostObjects (obj) {
Object.keys(obj).forEach(k => {
if (typeof obj[k] === 'object') {
getUpdatedLengthOfInnerMostObjects(obj[k])
} else {
container = k + someFunc(obj[k]) + obj[k]
length += container.length
}
})
return length
}
const sampleObj = {
"key1": {
"key2": {
"key3": {
"key4a": {
"key5a": "value5a"
},
"key4b": {
"key5b": "value5b"
},
"key4c": {
"key5c": "value5c"
},
"key4d": {
"key5d": "value5d"
}
}
}
}
}
function someFunc (obj) {
// Some string manipulation here to return variable length, just returning static for simplicity of this example
return 'xxx'
}
console.log('length 1st try = ' + getUpdatedLengthOfInnerMostObjects(sampleObj))
console.log('length 2nd try = ' + getUpdatedLengthOfInnerMostObjects(sampleObj))
So the string to get the length of is:
key5axxxvalue5akey5bxxxvalue5bkey5cxxxvalue5ckey5dxxxvalue5d
It results to lengths of 60 and 120. I need it to output 60 and 60.
"length 1st try = 60"
"length 2nd try = 120"
But not sure how to. When I add this before the return statement in the getUpdatedLengthOfInnerMostObjects(), then it always just returns 0.
const tempLength = length
length = 0
return tempLength
What am I missing here??
Fiddle here:
https://jsfiddle.net/keechan/cs3prmLx/
Help!
You must move length variable into function scope.
try it :
var container = ''
function getUpdatedLengthOfInnerMostObjects (obj) {
let length = 0
let getResult = (obj) => {
Object.keys(obj).forEach(k => {
if (typeof obj[k] === 'object') {
getResult(obj[k])
} else {
container = k + someFunc(obj[k]) + obj[k]
length += container.length
}
})
}
getResult(obj);
return length
}
const sampleObj = {
"key1": {
"key2": {
"key3": {
"key4a": {
"key5a": "value5a"
},
"key4b": {
"key5b": "value5b"
},
"key4c": {
"key5c": "value5c"
},
"key4d": {
"key5d": "value5d"
}
}
}
}
}
function someFunc (obj) {
// Some string manipulation here to return variable length, just returning static for simplicity of this example
return 'xxx'
}
console.log('length 1st try = ' + getUpdatedLengthOfInnerMostObjects(sampleObj))
console.log('length 2nd try = ' + getUpdatedLengthOfInnerMostObjects(sampleObj))
I think you really want a dig function:
function dig(obj, func){
let v;
if(obj instanceof Array){
for(let i=0,l=obj.length; i<l; i++){
v = obj[i]; func(v, i, obj);
if(typeof v === 'object' && v !== null)dig(v, func);
}
}
else{
for(let i in obj){
v = obj[i]; func(v, i, obj);
if(typeof v === 'object' && v !== null)dig(v, func);
}
}
}
const sampleObj = {
"key1": {
"key2": {
"key3": {
"key4a": {
"key5a": "value5a"
},
"key4b": {
"key5b": "value5b"
},
"key4c": {
"key5c": "value5c"
},
"key4d": {
"key5d": "value5d"
}
}
}
}
}
let results = '';
dig(sampleObj, (v,k)=>{
if(typeof v === 'string'){
results += k+'xxx'+v;
}
});
console.log(results); console.log(results.length);
Note that you may have to add more conditions if other steps give you String results in your actual Object.

traversing a json for empty array value

i have a below json
{
"loanDetails": [
{
"vehicleDetail": {
"RCBookImageReferences": {
"imagePathReferences": [
{
}
]
}
},
"chargeDetails": [
{
}
],
"commissionDetails": [
{
}
],
"disbursementDetails": [
{
}
]
}
]
}
in the above json i need to traverse every key and if i find it emty then set the parent as empty array ie the output should be as below
{"loanDetails":[]}
i used the code below
function isEmpty(obj) {
for(var prop in obj) {
if(obj.hasOwnProperty(prop))
return false;
}
return true;
}
But it did not give me the expected result.I'm stuck here any help will be much helpful.
The function clean takes an object and loops over its keys, calling clean recursively
on each object-valued property.
If the result of cleaning is an empty object, delete the key in question.
If the object itself turns out to be empty, return undefined, triggering deletion of the property holding that object at the higher level.
function clean(obj) {
var isEmpty = true;
for (var key in obj) {
var val = obj[key];
if (val === null || typeof val !== 'object' || (obj[key] = clean(val))) {
isEmpty = false;
} else {
delete obj[key];
}
}
return isEmpty ? undefined : obj;
}
>> a = { x: 1, b: { y: [] }, c: { d: { } } }
>> clean(a)
<< Object {x: 1}
This should make it recursive. With two solutions.
Solution 1: empty test function
var boolValue = true;
for(var prop in obj) {
if(obj.hasOwnProperty(prop) && typeof obj[prop] === 'object')
{
boolValue = recursiveIsEmpty(obj[prop]);
}
else
{
return false;
}
}
return boolValue ;
//test and set empty string
recursiveIsEmpty(jsonDataObj['loanDetails']) ? jsonDataObj['loanDetails'] = [] : null;
Solution 2 recursive empty function that empties parent obj
function recursiveIsEmpty(obj) {
var boolValue = true;
for(var prop in obj) {
if(obj.hasOwnProperty(prop) && typeof obj[prop] === 'object')
{
boolValue = recursiveIsEmpty(obj[prop]);
if (boolValue)
{
delete obj[prop]; //an object is empty. Delete from parent;
}
}
else
{
return false;
}
}
return boolValue; //returns an empty object
}
recursiveIsEmpty(jsonDataObj['loanDetails']) //returns jsonDataObj['loanDetails'] = [];
This checks if obj has a property that is an object. If so load that object and check it's properties. If not return false, because that will be string or number and that confirms the object is not empty.
Your JSON-string is not valid. When corrected, you can use a reviver function parameter (see MDN) to remove 'empty' arrays (aka properties with criteria you specify).
To be clear, the reviver function takes care of the traversing on all levels of the parsed object. If it returns undefined the property is removed from the object. The reviver used in the snippet thus removes all properties containing arrays with empty objects, or empty arrays.
The snippet demonstrates this.
// json string corrected
var foo = '{"loanDetails": [{"vehicleDetail": {"RCBookImageReferences": '+
'{"imagePathReferences": [{}]}}, "chargeDetails": [{}],'+
'"commissionDetails": [{}],"disbursementDetails": [{}]}]}';
// parse it, using reviver parameter
var fooparsed = JSON.parse( foo,
function (key, value) { //<= reviver here
return (value.length && value.length == 1 &&
value[0] instanceof Object &&
Object.keys(value[0]).length == 0) ||
value instanceof Array && !value.length
? undefined : value;
}
);
// print
Helpers.log2Screen( Object.print(fooparsed) );
<script src="http://kooiinc.github.io/JSHelpers/Helpers-min.js"></script>
if you are doing this using ajax then you should go with seriallizing the jason array using javascript.
at the time of passing data through json
data: "your data",
use this
data:$(form).serialize(),
it will pass all the key of that form which you are passing ,
if you want to see its result the try to print it on console
var inputObj = {
"loanDetails": [{
"vehicleDetail": {
"RCBookImageReferences": {
"imagePathReferences": [{}]
}
},
"chargeDetails": [{}],
"commissionDetails": [{}],
"disbursementDetails": [{}]
}, {
"vehicleDetail": {
"RCBookImageReferences": {
"imagePathReferences": [{
"Valid": "Working"
}]
}
},
"chargeDetails": [{}],
"commissionDetails": [{}],
"disbursementDetails": [{}]
}],
"Superman": {
"Name": ""
},
"SpiderMan": {
"Name": "Senthil"
}
}
function flatten(target, opts) {
var output = {},
opts = opts || {},
delimiter = opts.delimiter || '.'
function getkey(key, prev) {
return prev ? prev + delimiter + key : key
};
function step(object, prev) {
Object.keys(object).forEach(function(key) {
var isarray = opts.safe && Array.isArray(object[key]),
type = Object.prototype.toString.call(object[key]),
isobject = (type === "[object Object]" || type === "[object Array]")
if (!isarray && isobject) {
return step(object[key], getkey(key, prev))
}
output[getkey(key, prev)] = object[key]
});
if (Object.keys(object) == "") {
if (object instanceof Array) {
output[prev] = [];
} else {
output[prev] = {};
}
}
};
step(target)
return output
};
function unflatten(target, opts) {
var opts = opts || {},
delimiter = opts.delimiter || '.',
result = {}
if (Object.prototype.toString.call(target) !== '[object Object]') {
return target
}
function getkey(key) {
var parsedKey = parseInt(key)
return (isNaN(parsedKey) ? key : parsedKey)
};
Object.keys(target).forEach(function(key) {
var split = key.split(delimiter),
firstNibble, secondNibble, recipient = result
firstNibble = getkey(split.shift())
secondNibble = getkey(split[0])
while (secondNibble !== undefined) {
if (recipient[firstNibble] === undefined) {
recipient[firstNibble] = ((typeof secondNibble === 'number') ? [] : {})
}
recipient = recipient[firstNibble]
if (split.length > 0) {
firstNibble = getkey(split.shift())
secondNibble = getkey(split[0])
}
}
// unflatten again for 'messy objects'
recipient[firstNibble] = unflatten(target[key])
});
//Array Check
var keys = Object.keys(result);
if (keys.length > 0 && keys[0] === "0") {
var output = [];
keys.forEach(function(key) {
output.push(result[key])
});
return output;
}
return result
};
var flatted = flatten(inputObj);
var keys = Object.keys(flatted);
keys.forEach(function(key) {
if (JSON.stringify(flatted[key]) === "{}" || JSON.stringify(flatted[key]) == "") {
// console.log(key)
delete flatted[key];
var paths = key.split(".");
if (paths.length >= 2) {
var int = parseInt(paths[1])
if (isNaN(int)) {
key = paths[0];
flatted[key] = {};
} else {
key = paths[0] + "." + int;
flatted[key] = {};
}
var newKeys = Object.keys(flatted);
for (var j = 0; j < newKeys.length; j++) {
var omg = newKeys[j];
if (omg.indexOf(key) != -1 && omg.length > key.length) {
delete flatted[key];
}
}
}
}
})
console.log(flatted)
var output = unflatten(flatted);
alert(JSON.stringify(output))

Typescript Dictionary Coding of Effective Javascript dict function into class

What would be a good Typescript class derived from the example in "Effective Javascript" dict example
function Dict(elements) {
// allow an optional initial table
this.elements = elements || {}; // simple Object
this.hasSpecialProto = false; // has "__proto__" key?
this.specialProto = undefined; // "__proto__" element
}
Dict.prototype.has = function (key) {
if (key === "__proto__") {
return this.hasSpecialProto;
}
// own property only
return {}.hasOwnProperty.call(this.elements, key);
};
Dict.prototype.get = function (key) {
if (key === "__proto__") {
return this.specialProto;
}
// own property only
return this.has(key)
? this.elements[key]
: undefined;
};
Dict.prototype.set = function (key, val) {
if (key === "__proto__") {
this.hasSpecialProto = true;
this.specialProto = val;
} else {
this.elements[key] = val;
}
};
Dict.prototype.remove = function (key) {
if (key === "__proto__") {
this.hasSpecialProto = false;
this.specialProto = undefined;
} else {
delete this.elements[key];
}
};
The bot wants me to enter more explanation which I would regard as verbosity. Who knows when I will type enough to please it. It also wants me to indent things perfectly, too.
Assuming your original code is correct. The following is the code transformed to TypeScript:
class Dict {
hasSpecialProto = false; // has "__proto__" key?
specialProto = undefined; // "__proto__" element
constructor(public elements = {}) {
// allow an optional initial table
}
has(key) {
if (key === "__proto__") {
return this.hasSpecialProto;
}
// own property only
return {}.hasOwnProperty.call(this.elements, key);
}
get(key) {
if (key === "__proto__") {
return this.specialProto;
}
// own property only
return this.has(key)
? this.elements[key]
: undefined;
}
set(key, val) {
if (key === "__proto__") {
this.hasSpecialProto = true;
this.specialProto = val;
} else {
this.elements[key] = val;
}
}
remove(key) {
if (key === "__proto__") {
this.hasSpecialProto = false;
this.specialProto = undefined;
} else {
delete this.elements[key];
}
}
}
Note that TypeScript will know what this means in the functions + I used a default parameter in the constructor.
If you are looking for something more powerful (and tested) with generics take a look at TypeScript collections : https://github.com/basarat/typescript-collections#included-data-structures

Recursively manipulate javascript object data ends

Is there a way to walk through an arbitrary Javascript object, and alter it at its data ends, wherever its not another nested object?
So given the below, could I log an object where '123', 'bar', 'die', 'or' become 'xyz'?
var jso = {
hello:[
{ foo:'bar' },
{ abc: { def:'123' } }
],
world:[
{ ride:['or','die'] }
]
};
function recurse(object) {
if (Object.prototype.toString.call(object) === '[object Array]') {
var l = object.length;
while(l--){
recurse(object[l])
}
} else if(typeof object === 'object') {
for(var key in object) {
recurse(object[key])
}
} else {
object = 'xyz';
}
}
recurse(jso)
console.log(jso)
object = 'xyz';
That won't work, as it just changes the object variable that is local to the function call. To actually modify an object, you need to assign to a property:
function recurse(object) {
if(Object.prototype.toString.call(object) === '[object Array]'){
for (var l = object.length; l--; ) {
if (typeof object[l] == 'object')
recurse(object[l]);
else
object[l] = 'xyz';
}
} else {
for(var key in object) {
if (typeof object[key] == 'object')
recurse(object[key]);
else
object[key] = 'xyz';
}
}
}
or (better)
function recurse(object) {
if (typeof object !== 'object')
return 'xyz';
if (Object.prototype.toString.call(object) === '[object Array]'){
for (var l = object.length; l--; ) {
object[l] = recurse(object[l]);
}
} else {
for (var key in object) {
object[key] = recurse(object[key])
}
}
return object;
}
Object.keys is nice in these situations.
function recurse(datum) {
if (Array.isArray(datum)) {
datum.forEach(function (arrayItem, idx) {
datum[idx] = recurse(datum[idx]);
});
return datum;
} else if (typeof datum === 'object') {
Object.keys(datum).forEach(function (key) {
datum[key] = recurse(datum[key]);
});
return datum;
} else {
return 'xyz';
}
}
JSFiddle
Nice and simple:
function recurse(object) {
Object.keys(object).forEach(function(key) {
if (typeof object[key] == "object") {
recurse(object[key]);
} else {
object[key] = "xyz";
}
});
}

(Un)Set nested array values by string input

I have a function like this:
Session.get = function(key) {
if (!window["_SESSION"] || typeof key == 'undefined') {
return window["_SESSION"] || {};
}
if (key.indexOf('.') === -1) {
return window["_SESSION"][key] || {};
}
var keyArr = key.split('.'), val = window["_SESSION"];
for ( var i = 0; i < keyArr.length; i++) {
if (typeof val[keyArr[i]] === 'undefined') {
return null;
}
val = val[keyArr[i]];
}
return val;
}
This function allows me to get nested values without temporary variable outside of the function. Example Session.get('var.nestedvar') is returns value of window[_SESSION']['var']['nestedvar'].
Bat how can I (un)set variables like so? Tried to delete val; but didn't work.. How do the javascript references work? Does anybody know any alternative to accomplish similiar functionality?
You can delete by parent like this:
[10:00:00.380] a = {'root': {'home':'~'}}
[10:00:00.385] ({root:{home:"~"}})
--
[10:00:09.625] b = a['root']
[10:00:09.631] ({home:"~"})
--
[10:00:20.569] delete b['home']
[10:00:20.573] true
[10:00:21.684] a
[10:00:21.688] ({root:{}})
You can use a slight modification of your existing code, like this:
Session.delete = function(key) {
if (!window["_SESSION"] || typeof key == 'undefined') {
return false;
}
if (key.indexOf('.') === -1) {
if (key) {
delete key;
return true;
}
}
var keyArr = key.split('.'), val = window["_SESSION"];
var keyDepth = keyArr.length;
for ( var i = 0; i < keyDepth-1; i++) {
if (typeof val[keyDepth] === 'undefined') {
return null;
}
val = val[keyDepth];
}
if (val[keyDepth-1]) {
delete val[keyDepth-1];
return true;
}
return false;
}

Categories