In this code i intend to find all the nested object literals in a parent object.One of my nested object has an array called places as its own property.I have a recursive function called getObjNum which goes through every property and finds nested object literals inside parent object.
In my Parent object there are three nested object literals.One of them has an array as property.So container array which is supposed to store all the found nested object literals must have 3 indexes.But array places also included as fourth index to container array.I found
typeof(array)=='object' returns true;
arr instanceof Object also returns true;
How can i prevent the place array to be inserted to container array along with other object literals??
var getValue;
var parentObj = {
parentProp: 10,
childObj: {
childProp: 20,
grandChildObj: {
y: {
z:'lol',
places:['newyork','canada','dhaka']
}
}
}
}
var arr=[];
var container=[];
var count=0;
function getObjNum(obj){
var prop=Object.getOwnPropertyNames(obj);
for(i=0;i<prop.length;i++){
if(typeof(obj[prop[i]])=='object'){
container.push(obj[prop[i]]);
count++;
getObjNum(obj[prop[i]]);
}
}
}
getObjNum(parentObj);
console.log(container);
As pointed out in the comments, you can use instanceof Array to check if an object is an array or not, like so:
function getChildObjects(obj, returnArr) {
return Object.keys(obj).reduce(function (arr, key) {
var prop = obj[key];
if (typeof prop === 'object' && !(prop instanceof Array)) {
arr.push(prop);
arr = getChildObjects(prop, arr);
}
return arr;
}, returnArr || []);
}
var parentObj = {
parentProp: 10,
childObj: {
childProp: 20,
grandChildObj: {
y: {
z:'lol',
places:['newyork','canada','dhaka']
}
}
}
};
var childs = getChildObjects(parentObj);
console.log(childs, childs.length);
Related
This question already has answers here:
Accessing nested JavaScript objects and arrays by string path
(44 answers)
access object through dot-syntax string path
(2 answers)
Access object child properties using a dot notation string [duplicate]
(13 answers)
Closed 4 years ago.
I am writing a function to convert array to List using Javascript.
If the input array is as below:
let inputArray = [1,2,3]
The output object should be like the below:
let outputList = {
value: 1,
rest: {
value: 2,
rest: {
value : 3,
rest: null } } }
I have the below function that accepts a nested object as its parameter and returns a string that represents where in the object, the property is null:
function getLastValue(object) {
let s = '';
if (object.rest) {
return s += '[rest]' + getLastValue(object.rest);
} else {
return s;
}
And the below function that converts an array to a list:
var list = {value: '', rest: null};
function constructList(arr) {
for (let prop of arr) {
let lastValue = getLastValue(list);
`${list}${lastValue}`.value = prop;
`${list}${lastValue}`.rest = null;
}
return list;
}
The constructList function fails to work as ${list}${lastValue} is a string. I need to convert the above from
'list[rest][rest]'
to
list[rest][rest]
Any help is appreciated!
This would be a great place to use reduceRight - construct the innermost object first, and have it be the new value of the accumulator, which is assigned to the next innermost object's rest property, and so on:
const constructList = arr => arr.reduceRight(
(rest, value) => ({ value, rest }),
null
);
console.log(
constructList([1, 2, 3])
);
To fix your original code, rather than constructing a string that attempts to refer to the nested object, iterate through the nested structure to find the innermost rest property instead, and return the object that doesn't contain a truthy rest property:
function getLastValue(obj) {
while (true) {
if (!obj.rest) return obj;
obj = obj.rest;
}
}
var list = {
value: '',
rest: null
};
function constructList(arr) {
for (let prop of arr) {
const nestedObj = getLastValue(list);
nestedObj.value = prop;
nestedObj.rest = {};
}
getLastValue(list).rest = null;
return list;
}
console.log(
constructList([1, 2, 3])
);
I have this code
this.data_table.editedIndex = this.data_table.items.indexOf(item);
this.data_table.editedItem = Object.assign({}, item);
this.data_table.edit.tabs.currentTab = 0;
this.data_table.dialog = true;
but i'm noticing an issue where when the item has an array, i think the same array gets put in the new object. How can I change it so that it makes a new copy of the array? Preferably a deep copy of the array.
Instead of using Object.assign create a helper method to iterate through the object, determine if a value is an array and explicitly copy it using a spread operator ( ... )
let copyObj = o => {
let new_o = {};
for (let k of Object.keys(o)) {
(Array.isArray(o[k])) ? new_o[k] = [...o[k]]: new_o[k] = o[k];
}
return new_o;
}
//create copy function
let copyObj = o => {
let new_o = {};
for (let k of Object.keys(o)) {
(Array.isArray(o[k])) ? new_o[k] = [...o[k]]: new_o[k] = o[k];
}
return new_o;
},
//our object
obj = {
aString: "hola!",
anArray: [1, 2, 3, 4, 5, 6]
},
//our new object
nObj = copyObj(obj);
//change the old object
obj.anArray[3] = 555555;
//the old object array is changed, but the new one isn't.
console.log("new object: ", nObj, "old object: ", obj);
Note to deep clone the Array and return entirely new Objects and Arrays from within the first level of the Array or deeper, you would implement this same technique with further conditionals and recursively call the function.
Lodash will do the trick. Try method _.merge(obj1, obj2)
https://lodash.com/docs/4.17.11#merge
Array and plain object properties are merged recursively.
I have a data structure like the following:
obj
name
parent
name
parent
name
parent
I'm trying to do a recursive function to get the name element for as long as there is a parent element. I've come up with the following code, but it doesn't work because it converts the result to a string (and not an object). Can someone give me some advice on how to best achieve this. The nesting of parent elements is varied, not fixed (even though above I only specified 3 layers). It can range from 1 to 100.
My Desired Result
My end goal is to extract all the 'name' elements from every 'parent' down the hierarchy (and push them to an array).
function getElem(obj){
var result = '';
var parent = '.parent';
var temp = '';
if(!obj.parent){
return obj.name
}
else {
//structure is obj.parent.parent.parent...name
temp += parent;
result = obj + temp + '.name';
console.log(result);
getElem(result);
}
}
getElem(e.data);
function getElem(obj, arr) {
arr = arr || [];
if (obj.name) {
arr.push(obj.name);
}
if (obj.parent) {
return (getElem(obj.parent, arr));
}
else {
return (arr);
}
}
JSFiddle
Assuming that your data structure looks like this
var obj = {
name: 'abc',
parent: {
name: 'def',
parent: {
name: 'ghi',
parent: {
name: 'jkl'
}
}
}
};
function for loop that walks recursively for "parent" key by assigning "parent" key's value in obj and breaks the loop when the key "parent" is not available...
function get_names(obj, key) {
var names = [];
if(key == "undefined") {
key = "parent"; // default value of key
}
do {
if(typeof obj === "undefined") {
break; // breaks the loop when obj/parent is undefined
}
names.push(obj.name); // pushes all the elements named as 'name'
} while(obj = obj.parent);
return names;
}
Logs the array in console
console.log(get_names(obj));
I don't think you need recursion.
function getElem(obj) {
var names = [obj.name];
while (obj.parent) {
obj = obj.parent;
names.push(obj.name);
}
return names;
}
I have an array like this:
var myArray = new Array();
myArray['foo'] = {
Obj: {
key: value
}
};
myArray['bar'] = {
Obj: {
key: value
}
};
When I do console.log(myArray) I just get empty [ ]. And when I try to iterate the array using jQuery's each the function doesn't run.
How can I get the 'foo' and 'bar' parts of the array?
Example code:
console.log(myArray); // [ ]
jQuery.each(myArray, function(key, obj) {
console.log(key); // should be 'foo' following by 'bar'
});
In addition, why does this work:
jQuery.each(myArray[foo], function(obj, values) {
// Why does this work if there are no associative arrays in JS?
});
you can get keys by:
Object.keys(variable name);
it returns array of keys.
You need to define it as an object if you want to access it like that:
var myObj= {};
myObj.foo = ...;
myObj.bar = ...;
Now you can access the properties like myObj["bar"] or myObj.bar
Note:
To loop through all the properties it's wise to add an additional check. This is to prevent you from looping through inherited properties.
for (var key in obj) {
if (obj.hasOwnProperty(key)) {
// Do stuff.
}
}
Array is a collection where each element has an index.
To add element to array you can use push method
myArray.push('someValue');
or set element by index (if length of array < index):
myArray.push('someValue1');
myArray.push('someValue1');
myArray[0] = 'new someValue1';
Note that array is an instance of Object class, so you can add/edit any property of this object:
myArray.foo = '1';
myArray['bar'] = '2';
In this case you will not add new element to array, you defining new properties of object.
And you don't need to create object as Array if you don't wont to use indexes.
To create new object use this code:
var myObj = {};
To get all properties of object see
How to get all properties values of a Javascript Object (without knowing the keys)?
var myArray = {};
myArray['foo'] = { 'key': 'value' }
myArray['bar'] ={ 'key': 'value' }
console.log(myArray)
jQuery.each(myArray['foo'], function(obj, values) {
console.log(obj, values)
});
Demo
With your Array of Objects you could use this function:
var getKeys = function(obj) {
if (!(typeof obj == "object")) return [];
var keys = [];
for (var key in obj) if (obj != null && hasOwnProperty.call(obj, key)) keys.push(key);
return keys;
};
getKeys(myArray) would give you an array of your Keys.
This is basically a cleared up version of underscores _.keys(myArray) function. You should consider using underscore.
// $.each() function can be used to iterate over any collection, whether it is an object or an array.
var myArray = {};
myArray['alfa'] = 0;
myArray['beta'] = 1;
$.each(myArray, function(key, value) {
alert(key);
});
Note: checkout http://api.jquery.com/jQuery.each/ for more information.
Consider:
var object = {
foo: {},
bar: {},
baz: {}
}
How would I do this:
var first = object[0];
console.log(first);
Obviously, that doesn’t work because the first index is named foo,
not 0.
console.log(object['foo']);
works, but I don’t know it’s named foo. It could be named anything. I just want the first.
Just for fun this works in JS 1.8.5
var obj = {a: 1, b: 2, c: 3};
Object.keys(obj)[0]; // "a"
This matches the same order that you would see doing
for (o in obj) { ... }
If you want something concise try:
for (first in obj) break;
alert(first);
wrapped as a function:
function first(obj) {
for (var a in obj) return a;
}
they're not really ordered, but you can do:
var first;
for (var i in obj) {
if (obj.hasOwnProperty(i) && typeof(i) !== 'function') {
first = obj[i];
break;
}
}
the .hasOwnProperty() is important to ignore prototyped objects.
This will not give you the first one as javascript objects are unordered, however this is fine in some cases.
myObject[Object.keys(myObject)[0]]
If the order of the objects is significant, you should revise your JSON schema to store the objects in an array:
[
{"name":"foo", ...},
{"name":"bar", ...},
{"name":"baz", ...}
]
or maybe:
[
["foo", {}],
["bar", {}],
["baz", {}]
]
As Ben Alpert points out, properties of Javascript objects are unordered, and your code is broken if you expect them to enumerate in the same order that they are specified in the object literal—there is no "first" property.
for first key of object you can use
console.log(Object.keys(object)[0]);//print key's name
for value
console.log(object[Object.keys(object)[0]]);//print key's value
There is no way to get the first element, seeing as "hashes" (objects) in JavaScript have unordered properties. Your best bet is to store the keys in an array:
var keys = ["foo", "bar", "baz"];
Then use that to get the proper value:
object[keys[0]]
ES6
const [first] = Object.keys(obj)
Using underscore you can use _.pairs to get the first object entry as a key value pair as follows:
_.pairs(obj)[0]
Then the key would be available with a further [0] subscript, the value with [1]
I had the same problem yesterday. I solved it like this:
var obj = {
foo:{},
bar:{},
baz:{}
},
first = null,
key = null;
for (var key in obj) {
first = obj[key];
if(typeof(first) !== 'function') {
break;
}
}
// first is the first enumerated property, and key it's corresponding key.
Not the most elegant solution, and I am pretty sure that it may yield different results in different browsers (i.e. the specs says that enumeration is not required to enumerate the properties in the same order as they were defined). However, I only had a single property in my object so that was a non-issue. I just needed the first key.
You could do something like this:
var object = {
foo:{a:'first'},
bar:{},
baz:{}
}
function getAttributeByIndex(obj, index){
var i = 0;
for (var attr in obj){
if (index === i){
return obj[attr];
}
i++;
}
return null;
}
var first = getAttributeByIndex(object, 0); // returns the value of the
// first (0 index) attribute
// of the object ( {a:'first'} )
To get the first key of your object
const myObject = {
'foo1': { name: 'myNam1' },
'foo2': { name: 'myNam2' }
}
const result = Object.keys(myObject)[0];
// result will return 'foo1'
Based on CMS answer. I don't get the value directly, instead I take the key at its index and use this to get the value:
Object.keyAt = function(obj, index) {
var i = 0;
for (var key in obj) {
if ((index || 0) === i++) return key;
}
};
var obj = {
foo: '1st',
bar: '2nd',
baz: '3rd'
};
var key = Object.keyAt(obj, 1);
var val = obj[key];
console.log(key); // => 'bar'
console.log(val); // => '2nd'
My solution:
Object.prototype.__index = function(index)
{
var i = -1;
for (var key in this)
{
if (this.hasOwnProperty(key) && typeof(this[key])!=='function')
++i;
if (i >= index)
return this[key];
}
return null;
}
aObj = {'jack':3, 'peter':4, '5':'col', 'kk':function(){alert('hell');}, 'till':'ding'};
alert(aObj.__index(4));