Generic JSON Element Access - javascript

My colleague wrote a function to get all the keys out of a JSON object and check them against ones we're interested in. What I can't seem to search Google correctly for is how to take the variable holding the key name and use it to get the values. Obviously, idx itself is not a member of the object, but it contains the member name. How do I use idx to access obj?
$.each(JSON.parse(data[0][i]), function(idx, obj){
for(var j = 0; j < searchKeys.length; j++){
if (idx == searchKeys[j]) {
//How do I do this correctly?
injectLoc.innerHTML += panelMaker(obj.idx, idx, "green", "gears");
}
}
});

You can use it similar to how you'd access an element on an array.
var value = obj[idx];
You can access a property on an object in JavaScript like obj.prop or obj["prop"] or obj[idx] where idx === "prop".

In JSON,
Accessing elements by index --> obj[idx]
Accessing values by keys --> obj.key or obj["key"]
Note: If key has spaces use only --> obj["key"]

You can use Object.keys() to iterate keys of the object. So the function could potentially work like this:
Object.keys(obj).forEach((key, index) => {
if(index === key){
injectLoc.innerHTML += panelMaker(obj[key], index, "green", "gears");
}
})

Related

I have an issue with removing an object key with a for in loop

I'm using a for x in loop to check if a value is == to [] and if so remove the property using remove but it just does not seem to work.
const whosOnline = (a) => {
var obj = { online:[],
offline:[],
away:[] };
for(let i = 0; i < a.length; i++){
if(a[i].lastActivity > 10 && a[i].status == 'online'){obj.away.push(a[i].username)}
else if(a[i].status == 'offline'){obj.offline.push(a[i].username)}
else{obj.online.push(a[i].username)}
}
for(let x in obj){
console.log(obj[x])
if(obj[x] === []){delete obj[x]}}
return obj
}
you were close, however you also need to reference the array index for each object key value. Comments explaining this in the code below.
var obj = { online:[],
offline:[],
away:[] };
for(var x in obj){
if(!obj[x][0]){ // The 0 is the index inside the online array, next loop it will be the offline array and then the away array.
console.log('The array is empty');
// Do what you want to do now that it is empty
// This will continue to loop through and check the value of all the keys in the object.
}
}
console.log('done');
Good luck -
Mitch from
https://spangle.com.au
Using some debugging (simply testing if a console.log gets printed for instance) you find that your if-condition is never true.
This is because you test if an array equals a newly created empty array. This can never be the case, because objects are compared by object reference instead of value.
Instead you want to probably test to see if your array is empty by doing ‘if(obj[x].length===0)’ (or shorter: ‘if(!obj[x].length)’)

Search value in object

I have following object im not sure how to proceed.
Object image
How can I go through all objects and select the content array and search for a value x. And when the value x is in the object I need to get the object title from the object where the value was found.
Can anyone give me a hint how I can solve this problem?
you can use for...in to iterate over the object and indexOf() to check if a key exists in the array content. something like this:
function searchVal(x){
for(var key in obj){
if(obj[key].hasOwnProperty('content') && obj[key].content.includes(x))
return key;
}
}
You can use for...in to iterate the object keys, then a regular for loop to check the content array for your specific value:
function findTitle(x) {
for (var key in obj) {
for (var i = 0; i < obj[key].content.length; i++) {
if (obj[key].content[i] === x) {
return key;
}
}
}
}
let name = Object.values( obj /*your main object*/ )
.find( obj => obj.content.includes(x) )
.name;
You could find the first object in the Objects values of your main obj, that has a property content which includes x, then get the name of that object.

How to join Array Values as keys to get jSON object value

I have been working on a function that loops through a JSON object recursively, and want to use each key it finds as the class value of an element to change the .text value of that element in jQuery. So, far so good, however, as I am able to get the Keys recursively as well, I'm struggling on finding a way to input all of those keys to get each json objects values:
function eachRecursive(obj, aKey)
{
aKey = aKey === null ? '' : aKey;
for (var k in obj)
{
if (typeof obj[k] == "object" && obj[k] !== null)
{
aKey += k + '_';
eachRecursive(obj[k], aKey);
}
else
{
if (obj.hasOwnProperty(k))
{
console.log(obj[k]);
if ($('.player_' + aKey + k).length)
{
var props = aKey.split('_');
props.clean("");
$('.player_' + aKey + k).text(obj[k]);
}
}
// might not even need this.
aKey = '';
}
}
}
So, text(obj[k]) isn't going to work here since the json is looping through objects inside objects recursively.
So, aKey is a string that gets used to check if the class exists (should be appending each key of the json object into it. Than should check if exists, if it does exist, should plug in the value into the .text of that element.
But what I'm sruggling here with is how to get the value from all of the keys that get plugged into an array called, props. So I will need to use each value in the array as keys for obj object to get the corresponding json value.
Can someone please help me here?
The .clean prototype added to Array just simply removes any empty values in the array. Specifically the last array index (since it splits on _).
How to pass array values into obj to get the json value?
For Example, if:
var props = ['name', 'first', 'last'];
// How to do this so we can get the value?
obj['name']['first']['last'][k]
Iterate over the props array and lookup the value in turn using bracket notation.
var value = obj;
for (var i = 0; i < props.length; i++) {
value = value[props[i]];
}
value = value[k];

For loop is not working with json data

I'm trying to make a loop in javascript with the following code. It's getting length from json data.
The console.log(albums.data.length); line is working and returning 3. Why the loop is not working then?
The console.log(x); is not returning anything, even not blank line.
There is also no error in console.
function getBestPhoto(albums){
console.log(albums);
console.log(albums.data.length);
for(var x in albums.data.length){
console.log(x);
for(var y in albums.data[x].photos.length){
console.log(y);
}
}
}
I have tried another type of loop(for(var i = 0; i < blabla; i++)) but its not working too.
Edit:
I wanna use
for(var x = 0; x < albums.data.length; x++){
console.log(albums.data[x].photos.id);
}
instead of
for(var x in albums.data){
How can i do it?
You should remove .length from loops
function getBestPhoto(albums){
console.log(albums);
console.log(albums.data.length);
for(var i = 0; i < albums.data.length; i++){
var x = albums.data[i];
console.log(x);
for(var j = 0; j < albums.data[i].photos.length; j++){
var y = albums.data[i].photos[j];
console.log(y);
console.log(albums.data[i].photos[j].id);
}
}
}
The for-in loop is not for arrays, it is for iterating over properties/fields of an object. If albums.data is an array, you should use the forEach loop statement instead. If albums.data is an object, and you are trying to access its properties/fields/attributes, you can use the for-in construct.
If albums.data is an array, try:
albums.data.forEach(function(element, index) {
// Here you have access to each element (object) of the "albums.data" array
console.log(element.toString());
// You can also access each element's properties/fields if the element is an
// object.
// If the element is an array itself, you need to iterate over its elements
// in another inner foreach.
// Here we are accessing the "photos" property of each element - which itself
// is another array.
element.photos.forEach(function(photo, index) {
// Here you have access to the elements of the "photos" array
// Each element of the "photos" array is put in the photo variable.
// Assuming each element of the "photos" array is an object, you can access
// its properties, using the dot notation:
console.log("photo id=", photo.id);
// If the property name (e.g. "id") is not a valid javascript name
// (has some special symbols), use the bracket notation
console.log("photo URL=", photo["photo-url"]);
});
});
You can also use the lodash library for this (and many other neat functionalities).
If albums.data is an object, try:
for (var prop in albums.data) {
// Again, this construct is for accessing properties of an object
// (e.g. if albums.data is an object), not an array.
console.log("property name=" + prop + ", " + "property value=" +
albums.data[prop]);
}

Iterate over defined elements of a JS array

I'm using a JS array to Map IDs to actual elements, i.e. a key-value store. I would like to iterate over all elements. I tried several methods, but all have its caveats:
for (var item in map) {...}
Does iterates over all properties of the array, therefore it will include also functions and extensions to Array.prototype. For example someone dropping in the Prototype library in the future will brake existing code.
var length = map.lenth;
for (var i = 0; i < length; i++) {
var item = map[i];
...
}
does work but just like
$.each(map, function(index, item) {...});
They iterate over the whole range of indexes 0..max(id) which has horrible drawbacks:
var x = [];
x[1]=1;
x[10]=10;
$.each(x, function(i,v) {console.log(i+": "+v);});
0: undefined
1: 1
2: undefined
3: undefined
4: undefined
5: undefined
6: undefined
7: undefined
8: undefined
9: undefined
10: 10
Of course my IDs wont resemble a continuous sequence either. Moreover there can be huge gaps between them so skipping undefined in the latter case is unacceptable for performance reasons. How is it possible to safely iterate over only the defined elements of an array (in a way that works in all browsers and IE)?
Use hasOwnProperty within for ... in to make sure that prototype additions aren't included:
for (var item in map)
if (map.hasOwnProperty(item)) {
// do something
}
There are three issues:
You should not use for...in to iterate arrays.
You are using the wrong data type for your requirements.
You are not using for...in correctly.
If you want to have something like a hash table then use a plain object:
var map = {};
map[123] = 'something';
map.foo = 'bar';
// same as map['foo'] = 'bar';
//...
It looks like an array, but it is not. It is an object with property 123. You can use either dot notation obj.key (only if the key is a valid identifier - 123 would not be valid so you have to use the following notation) or array notation obj['key'] to access object properties.
It seems that an object would be a more appropriate data structure.
But even then you should make a call to hasOwnProperty (every time you use for...in):
for(var key in obj) {
if(obj.hasOwnProperty(key)) {
//do something
}
}
This checks whether a property is inherited from the prototype (it will return false then) or is truly an own property.
Use the EcmaScript 5 builtin Object.keys, and on non ES5 browsers, define it thus:
Object.keys = function (o) {
var keys = [];
var hasOwnProp = Object.prototype.hasOwnProperty;
if (Object.prototype.toString.call(o) === '[object Array]') {
for (var k in o) {
if (+k === (k & 0x7fffffff) && hasOwnProp.call(o, k)) {
keys[keys.length] = k;
}
}
keys.sort(keys, function (a, b) { return a - b; });
} else {
for (var k in o) {
if (hasOwnProp.call(o, k)) {
keys[keys.length] = k;
}
}
}
return keys;
};
1) use an object like already suggested, it is by far the best solution.
2) if you for some reason need to use an array - don't be scared looping over it with
for(var i, len = arr.length;len < i;i++)
it's very very fast.
3) don't use $.each or similar methods if you want performance - they create a new callstack for every iteration, which is a huge overhead.
Don't use an array. Use an object hash instead
var map = {};
map[key] = value;
...
for (var key in map) {
do something to map[key]
}
You can't do a lot without actually doing a check to see if the value is undefined and then doing operation a or operation b. It would be better to use a predicate to determine if the value is undefined:
x = $.grep(x, function(v, i) { return (typeof(v) != "undefined"); });
There isn't. The only way would be to omit the items from the collection completely, any solution you come up with would still have to do a test on each element for the value.
You could come up with different methods of adding the items key/value to object literals or what have you, but you would still need to omit undefined entries if you do not wish to enumerate over them.

Categories

Resources