How to change value of JSON using for loop/ foreach? - javascript

I've tried to change the value of json depending on key, but my loop not work
here's the code:
var duce2 = [{
"pages": "foo1",
"hasil": ""
},
{
"pages": "foo2",
"hasil": ""
},
{
"pages": "foo3",
"hasil": ""
},
{
"pages": "foo4",
"hasil": ""
},
{
"pages": "foo5",
"hasil": ""
},
{
"pages": "foo6",
"hasil": ""
}
];
for (let key in this.duce2) {
console.log("jalan ga fornya");
if (this.duce2[key].pages == 'foo2') {
console.log("jalan ga ifnya");
this.duce2[key].hasil = '1';
}
}
console.log(duce2);
did i doing something wrong with the code above? the console.log doesn't appear on for and if
EDIT : my chrome dev console just showing this

I am not sure why you use "this.duce2" in your code.
However, some useful advices :
variables should be declared using the least permissive scope. Instead of declaring the array with "var", you should prefer "const"
arrays should not be traversed using the for...in construction (which is for object properties). Instead, you should prefer to use the forEach method.
The result would be:
const duce2 = [ ... ];
duce2.forEach((elem) => {
if (elem.pages === 'foo2') {
elem.hasil = '1';
}
});

Use duce2 instead of this.duce2,
You can iterate like this.
for (var key in duce2) {
if (duce2.hasOwnProperty(key)) {
if(duce2[key].pages=='foo2'){
//your code ,what needs to be done.
}
}
}
The for/in statement loops through the properties of an object.
Hope it helps..!

Related

Stringify and parse complex object with nested arrays from localStorage

I have a very complex dictionary object consisting of very deeply nested combinations of objects and arrays.
I use a custom deepCopyObject function to make a deep copy of my object throughout my code. That works fine, I'm only including it because it's the only way I'm able to copy the object without a shallow reference.
The issue comes when I try to store and retrieve it from localStorage with parse and stringify. The below code returns:
nextQuestion local_user_dict is [object Object]
test.html:1 Uncaught SyntaxError: Unexpected token o in JSON at position 1
The code below was structured by copying the object from the console in the browser and editing the keys/values. I left all of the structure intact including the "null" values which I didn't include but I assume is due to it being an array nested within the object.
I'm told that stringify and parse should work with deeply nested and complex objects including with arrays (Though I've read elsewhere online that's not true). How can I correctly pass this object and retrieve it from localStorage?
If I use my deep copy function on the object it works fine and displays as it should, the problem only occurs when stringifying and parsing from localStorage.
var test_dict = {
"questions": {
"obj1": {
"words": [
null,
{
"test1": {
"test2": "test7",
"test3": "test6"
},
"test4": "test5"
},
{
"test8": {
"test9": 0,
"test10": "2",
},
"test11": [
null,
{
"test12": {
"no": 0,
"yes": 1
},
"test13": "test14"
},
{
"test15": {
"no": 0,
"yes": 1
},
"test16": "test17"
},
{
"test18": {
"no": 0,
"yes": 1
},
"test19": "test20"
}
]
}
]
}
}
}
localStorage.setItem('user_dict', deepCopyObject(test_dict))
let local_user_dict = localStorage.getItem('user_dict')
console.log('nextQuestion local_user_dict is ', local_user_dict)
let parsed_local_user_dict = JSON.parse(local_user_dict)
console.log('nextQuestion parsed_local_user_dict is ', parsed_local_user_dict)
user_dict = deepCopyObject(parsed_local_user_dict)
console.log('nextQuestion user_dict is ', user_dict)
function deepCopyObject(inObject) {
let outObject, value, key
if (typeof inObject !== "object" || inObject === null) {
return inObject
}
outObject = Array.isArray(inObject) ? [] : {}
for (key in inObject) {
value = inObject[key]
outObject[key] = deepCopyObject(value)
}
return outObject
}
localstorage stores strings. not objects.
change
localStorage.setItem('user_dict', deepCopyObject(test_dict))
to
localStorage.setItem('user_dict', JSON.stringify(test_dict))
and ditch the copy. you can actually use JSON parse and stringify to copy objects.

Matching certain value in JSON Array using match() or find() in JavaScript

I'm looking for a function or method to overcome this issue
Here is the JSON Array
[{
"type": "radar",
"detail": [{
"subject": "sub1"
}, {
"subject": "sub2"
}]
}, {
"type": "bar",
"detail": [{
"subject": "sub1"
}, {
"subject": "sub2"
}]
}]
I'm hoping to identify the value of "type" which in this case would be "radar" and "bar",and match with the variable x。
Here's the code:
for(x in myarray)
{
if(myarray[x]['type']=="bar")
{
console.log("equal");
}
else
{
console.log("no result");
}
}
With this code,the result on the website console would be both "equal" and "no result",while I wish to print "equal" only.I understand the logic error in this code,but I couldn't figure out the correct way to fix it.
You can use Array.some for this which return true or false if one of the array element match with type "bar" then It will return true otherwise false
var data = [{
"type": "radar",
"detail": [{
"subject": "sub1"
}, {
"subject": "sub2"
}]
}, {
"type": "bar",
"detail": [{
"subject": "sub1"
}, {
"subject": "sub2"
}]
}]
if (data.some(val => val.type == "bar"))
console.log("Equal")
else
console.log("No record found");
let myArr = [
{ "type":"radar",
"detail": [
{ "subject":"sub1" },
{ "subject":"sub2" }
]
},
{ "type":"bar",
"detail": [
{ "subject":"sub1" },
{ "subject":"sub2" }
]
}
]
for(let x of myArr){
if(x.type === 'bar'){ console.log('equal')}
else { console.log('no result')}
}
In order to understand what went wrong with your code, first when you have a for loop, you need to have a let/var keyword as below:
for(let x of myArr)
Secondly, instead of using for..in loop, which it meant for looping property of objects, use for..of loop which meant for looping array.
Third, while looping myArr, each and every element x is an object and type is the property, so just use x.type to make the comparison.
Lastly, as others have mentioned, Array#some / Array#find is a better way to deal with finding existence of element in an array
Since the for loop runs for each object in the array, the first console log for equal is for matched type and second console log is for the unmatched type. So, to get only one console and to write more appropriate code, you can use Array.find() and then add a if-else block for that. Something like this:
var myarray = [ { "type":"radar", "detail": [{ "subject":"sub1" }, { "subject":"sub2" }] }, { "type":"bar", "detail": [{ "subject":"sub1" }, { "subject":"sub2" }] } ];
var match = myarray.find(({type}) => type === "bar");
if(match) {
console.log("equal");
} else {
console.log("no result");
}

How to know a particular value is available or not in a complex JSON

I have a json like this
myPermission=[
{
"root_permission_name":"HR",
"root_pk":3,
"child_list":[
{
"child_pk":8,
"child_permission_name":"Employee Management",
"sub_child_list":[
]
}
]
},
{
"root_permission_name":"Finance",
"root_pk":8,
"child_list":[
{
"child_pk":20,
"child_permission_name":"Fees",
"sub_child_list":[
{
"sub_child_permission_name":"Create Fees",
"sub_child_pk":5
},
{
"sub_child_permission_name":"Schedule Fee Collection Dates ",
"sub_child_pk":6
}
]
},
{
"child_pk":21,
"child_permission_name":"Category",
"sub_child_list":[
]
},
{
"child_pk":26,
"child_permission_name":"Finance Reports",
"sub_child_list":[
{
"sub_child_permission_name":"Report",
"sub_child_pk":17
},
{
"sub_child_permission_name":"Compare Transection",
"sub_child_pk":18
},
{
"sub_child_permission_name":"Fee Receipts",
"sub_child_pk":19
}
]
}
]
}
]
Is there a way that i can know whether the particular value (e.g. "Fees") is available or not in my json without using FOR loop ?
It will be appreciable if anyone solve this through RXJS.
Note : I dont have to use for loop
How about this:
var presence = JSON.stringify(yourJSON).indexOf('"Fees"') > -1;
or maybe this:
var presence = JSON.stringify(yourJSON).indexOf(':"Fees"') > -1;
I am just stringifying your object and then checking the presence of "Fees". If it is -1 then it is not present otherwise it is.
Is there a way that i can know whether the particular value (e.g. "Fees") is available or not in my json without using FOR loop ?
I assume you mean a for loop or any other looping construct. If so, the answer is "No, there isn't, not reasonably anyway."
So instead, you use a looping construct. Specifically, nested looping constructs, since Fees is on a child list:
var hasFees = myPermission.some(function(entry) {
return entry.child_list.some(function(child) {
return child.child_permission_name == "Fees";
});
});
Array#some calls its callback once for each entry in the array, stopping the first time the callback returns a truthy value. Its return value is true if the callback ever returned a truthy value, or false if not. So it's handy for searches like this.
Live Example:
var myPermission = [{
"root_permission_name": "HR",
"root_pk": 3,
"child_list": [{
"child_pk": 8,
"child_permission_name": "Employee Management",
"sub_child_list": [
]
}]
}, {
"root_permission_name": "Finance",
"root_pk": 8,
"child_list": [{
"child_pk": 20,
"child_permission_name": "Fees",
"sub_child_list": [{
"sub_child_permission_name": "Create Fees",
"sub_child_pk": 5
}, {
"sub_child_permission_name": "Schedule Fee Collection Dates ",
"sub_child_pk": 6
}]
}, {
"child_pk": 21,
"child_permission_name": "Category",
"sub_child_list": [
]
}, {
"child_pk": 26,
"child_permission_name": "Finance Reports",
"sub_child_list": [{
"sub_child_permission_name": "Report",
"sub_child_pk": 17
}, {
"sub_child_permission_name": "Compare Transection",
"sub_child_pk": 18
}, {
"sub_child_permission_name": "Fee Receipts",
"sub_child_pk": 19
}]
}]
}];
var hasFees = myPermission.some(function(entry) {
return entry.child_list.some(function(child) {
return child.child_permission_name == "Fees";
});
});
document.body.innerHTML = hasFees;
It's a bit unclear what you ask for. Based on the question, my guess is that this is an assignment where the teacher want the students to perform this in a functional approach rather than an imperative one. Hence the "no for loop" criteria.
The following function will iterate through all values, recursively, in the json and look for a specific value. If that value exists (no matter the property name) it'll return true.
It uses Array.some which will "tests whether some element in the array passes the test implemented by the provided function."
var hasPerm = myPermission
.some(function (arr) {
return hasPermission(arr, 'Fees')
});
console.log(hasPerm); // true/false
function hasPermission(arr, needle) {
return Object
.keys(arr)
.some(function(key) {
if (typeof arr[key] === 'object') {
return hasPermission(arr[key], needle);
} else {
return arr[key] === needle;
}
})
}
It can easily be extended to only look for the value at certain properties. As RxJS also has the some method it shouldn't be any problem to use in that context.

Convert objects to array in javascript

I really want to convert a object to array but my codes doesn’t worked.
data = "errors": {
"user": {
"name": "empty"
},
{
"length": "exceeds"
},
"title": {
"name": "empty"
},
{
"length": "exceeds"
}
}
Now I want to make them:
data = ["empty", "exceeds", "empty", "exceeds"];
What I’ve done so far is:
var arr = Object.keys(data[i].data.errors).map(function(k) {
return data[i].data.errors[k]
});
console.log(arr);
But the output is not what I expected. Please help. Thank very much.
If you always know the keys of the inner objects are going to be name and length a short way might be:
var out = Object.keys(data.errors).reduce(function (p, c) {
return p.concat([data.errors[c].name, data.errors[c].length]);
}, []);
DEMO

Using jQuery $.each with Json erroring with 1 result

Basically I am transforming a JSON result into html and using $.each it iterate through multiple keys. For example, I am pulling back facebook posts and iterating through the likes in that post.
The problem lies in the fact that when there are multiple "likes" everything works great! although when there is only 1 "like" the "source" key is removed from the result set and my javascript breaks because I expect it to be there. Any idea why the $.each is skipping a level for single nodes? The following is my code:
* JQUERY **
$.each(post.likes.item, function(i, like){
$(currentpost).find('div.cc_likes').append(like + ',');
console.log(like)
});
* JSON RESULT **
* Single Like
likes": {
"item": {
"source": {
"cta": "Mary Smith",
"url": "http:\/\/www.facebook.com\/",
"photo": {
"image": "https:\/\/graph.facebook.com\/"
}
}
},
Result in console:
Object
cta: "MaryAnn Smith"
photo: Object
url: "http://www.facebook.com/"
* Multiple Likes
"likes": {
"item": [
{
"source": {
"cta": "Bobby Carnes Sr.",
"url": "http:\/\/www.facebook.com",
"photo": {
"image": "https:\/\/graph.facebook.com\"
}
}
},
{
"source": {
"cta": "Jenna Purdy",
"url": "http:\/\/www.facebook.com\",
"photo": {
"image": "https:\/\/graph.facebook.com\"
}
}
},
{
"source": {
"cta": "Kevin Say",
"url": "http:\/\/www.facebook.com\",
"photo": {
"image": "https:\/\/graph.facebook.com\"
}
}
}
],
"count": "10",
"count_display": "10"
},
Result in console:
Object
source: Object
cta: "Kevin Smith"
photo: Object
url: "http://www.facebook.com/"
Since $.each() needs an array or array like object as argument, before using the object post.likes.item check if it is an array of not.
Following code will always pass an array to jQuery -
$.each([].concat(post.likes.item), function(i, like){
$(currentpost).find('div.cc_likes').append(like + ',');
console.log(like)
});
Explanation
[] is an empty array in JavaScript. Every array in JavaScript has a concat method.
[].concat(obj) concats obj to the empty array and returns an array.
if obj is not an array, result is [obj] which is an array with one item.
if obj is an array, then result is a deep copy of obj which is already an array.
More about concat method
if ( isArray ) {
for ( ; i < length; i++ ) {
value = callback.call( obj[ i ], i, obj[ i ] );
if ( value === false ) {
break;
}
}
} else {
for ( i in obj ) {
value = callback.call( obj[ i ], i, obj[ i ] );
if ( value === false ) {
break;
}
}
}
That is the jquery code being run on your JSON return. What's happening is, when you are looking at multiple results, it is looping through the array, return each base level object. However, when you are running it on a single return, it is looping through the object properties(in this case, "source"), and returning the value of that property.
You have two choices here. You can either make sure single items are still put in an array, or you can do a check for single items on the client side. The way Moazzam Khan suggests is the best way to do it in most cases.

Categories