Javascript array change value recursively - javascript

I'm stucking at changing an value of an array with unknown depth.
I want to iterate over it and change specific values, after all changes are done I want to receive the whole array back with the applied changes.
Code sample:
var array = [];
array.name = "Page";
array.inside = [];
array.inside.name = "Page inside";
array.inside.inside = [];
array.inside.inside.name = "Page inside inside";
array.inside.inside.inside = [];
function changeValue(array) {
for (var ii in array) {
if (typeof array[ii] === 'object') changeValue(array[ii]);
if (array.name) {
array.name = array.name + " changed";
}
console.log(array);
}
}
changeValue(array);

Try this:
var array = [];
array.name = "Page";
array.inside = [];
array.inside.name = "Page inside";
array.inside.inside = [];
array.inside.inside.name = "Page inside inside";
array.inside.inside.inside = [];
function changeValue(array) {
if (array.name) {
array.name = array.name + " changed";
}
console.log(array);
for (var ii in array) {
if (typeof array[ii] === 'object') changeValue(array[ii]);
}
}
changeValue(array);
Every time through the loop you are changing array.name. That is why you're results have ' changed changed'. Take the array.name modification out of the loop and it works just as expected.
Good luck.

Related

Concat in a for loop google app scripts javascript

I'm trying to filter in an array by data in another array using concat in a for loop. The elements of the following code are logging correctly, but the final array is logging an empty array.
function Shipments (){
var app = SpreadsheetApp;
var movementSS = app.getActiveSpreadsheet();
var infoSheet = movementSS.getSheetByName("Update Info");
var orderInfoSheet = movementSS.getSheetByName("Order Info");
var targetSheet = movementSS.getSheetByName("Shipments");
var ShipLogSS = app.openByUrl(URL).getSheetByName("Shipping Details");
var ShipArr = ShipLogSS.getRange(3,1,ShipLogSS.getLastRow(),ShipLogSS.getLastColumn()).getValues().
filter(function(item){if(item[1]!=""){return true}}).
map(function(r){return [r[0],r[1],r[2],r[4],r[10],r[11],r[16],r[18],r[23]]});
var supplierData = orderInfoSheet.getRange(3,6,orderInfoSheet.getLastRow(),1).getValues().
filter(function(item){if(item[0]!=""){return true}});
var supplierList = [];
for (var i in supplierData) {
var row = supplierData[i];
var duplicate = false;
for (var j in supplierList) {
if (row.join() == supplierList[j].join()) {
duplicate = true;
}
}
if (!duplicate) {
supplierList.push(row);
}
}
var supplierFilter = [];
for(var i = 0; i < supplierList.length; i++){
var shipments = ShipArr.filter(function(item){if(item[4]===supplierList[i][0]){return true}});
supplierFilter.concat(shipments);
}
Logger.log(supplierFilter);
}
Any help would be greatly appreciated!
You need to assign the result of concat onto the supplierFilter in order to see the changes in later iterations and in the outer scope.
You can also return the comparison done inside the .filter callback immediately, instead of an if statement - it looks a bit cleaner.
var supplierFilter = [];
for (var i = 0; i < supplierList.length; i++) {
var shipments = ShipArr.filter(function (item) { return item[4] === supplierList[i][0]; });
supplierFilter = supplierFilter.concat(shipments);
}
Logger.log(supplierFilter);

How to replace the $ symbol from json object key in nodejs

I am trying to remove the $ symbol from the key in json object(parsed). Normal JS file I used Remove special character in json key name in nodejs this answer mentioned and it is working fine. But I tried in nodejs due to async it is not working properly. The last formed object did not contain the entire modified value. So I tried the original function which is posted in the question but I am getting callback function not found error. I am using node 10.19 version. Is there any other way I can remove the $ symbol from my json object. Please give me a working solution. Actualy I am getting the input from yml file which gets converted to json string in jenkins. And again In my code I have parsed it. If there any library to directly convert yml file to json in jenkins that will also help.
var obj = {
'blue':{
'test:"value',
'$test1':'value1',
'tiger':'cheetah_growl',
'$jan':'cool'
}
}
Normal js file
var obj_new = { '$name': 'test1', '$auth_users': 'bajali_s' };
console.log("obj.blue",obj.blue.tiger);
var str = obj.blue.tiger;
var res = str.replace("_", " ");
console.log("res",res);
obj.blue.tiger = res;
console.log("obj.blue",obj.blue.$test1);
//const obj1 = {"example1.":"sometext.","example2.":"anothertext."};
const obj2 = {};
console.log(Object.getOwnPropertyNames(obj));
const obj1 = obj_new;
console.log("__",obj1);
/* for (const key of Object.getOwnPropertyNames(obj1)) {
obj2[key.replace(/[|&;$%#."<>()+,]/g, "")] = obj1[key];
} */
for (const key of Object.getOwnPropertyNames(obj1)) {
obj2[key.replace(/[|&;$%#."<>()+,]/g, "")] = obj1[key];
}
console.log("==",obj2);
var newjson = JSON.stringify(obj2);
console.log(newjson);
Here is what I did to remove the extra symbol in the key and value. I went through many sites and came up with this procedure hope it helps someone. I have also made it little dynamic.
var special_char_keys = ["creationType", "vm_location", "nic_location", "vnetlocation", "rg_location"];
var elements_to_delete = ["blueprint_info", "riglet_info", "quick_links"];
for (var a = elements_to_delete.length; a >= 0; a--) {
delete cloudProperties[elements_to_delete[a]];
}
var Mainkeys = Object.keys(cloudProperties);
console.log("Mainkeys", Mainkeys);
var total_keys_cloudproperties = Mainkeys.length;
for (var j = total_keys_cloudproperties; j > 0; j--) { // main json loop starts
for (const key of Object.getOwnPropertyNames(cloudProperties)) { // getting the main json keys
var obj1 = cloudProperties[key];
var obj2 = {};
var obj3 = {};
var obj4 = {};
var obj5 = {};
var formattedarray = [];
var keys = Object.keys(cloudProperties[key]);
//console.log("inner keys", keys);
var tasksToGo = keys.length;
//console.log("key length",tasksToGo);
for (var i = tasksToGo; i > 0; i--) {
for (const key1 of Object.getOwnPropertyNames(obj1)) {
// var item = obj1.get(key1); // this will get the value in the json based on key
if (Array.isArray(obj1[key1])) { // checking whether the key has value as [{},{}]
// console.log("for jsonarray case");
var temparray = obj1[key1]; // assigning the array to temparray
for (var k = 0; k < temparray.length; k++) { // for loop for getting each object value
var obj3 = temparray[k]; // assigning the inner object to a variable
var Arraykeys = Object.keys(obj3);
// console.log("array inner keys", Arraykeys);
var tasksToGo1 = Arraykeys.length;
for (var t = tasksToGo1; t > 0; t--) {
for (const key2 of Object.getOwnPropertyNames(obj3)) {
if (special_char_keys.includes(key2)) {
var tempvalue = obj3[key2];
var newvalue = tempvalue.replace("_", " ");
// console.log("newvalue", newvalue);
obj4[key2.replace(/[|&;$%#."<>()+,]/g, "")] = newvalue;
} else {
obj4[key2.replace(/[|&;$%#."<>()+,]/g, "")] = obj3[key2];
}
// obj4[key2.replace(/[|&;$%#."<>()+,]/g, "")] = obj3[key2];
}
if (Arraykeys == tasksToGo1) {
break;
}
temparray[k] = obj4;
// console.log("temparray[k] ======================", temparray[k]);
}
}
obj5[key1] = temparray;
cloudProperties[key] = obj5;
// console.log("vm case", cloudProperties[key]);
} else {
// console.log("for normal case");
if (special_char_keys.includes(key1)) {
var tempvalue = obj1[key1];
// console.log(obj1[key1]);
var newvalue = tempvalue.replace("_", " ");
// console.log("newvalue", newvalue);
obj2[key1.replace(/[|&;$%#."<>()+,]/g, "")] = newvalue;
cloudProperties[key] = obj2;
} else {
obj2[key1.replace(/[|&;$%#."<>()+,]/g, "")] = obj1[key1];
cloudProperties[key] = obj2;
}
//obj2[key1.replace(/[|&;$%#."<>()+,]/g, "")] = obj1[key1];
// cloudProperties[key] = obj2;
}
}
}
//console.log("obj2",obj2);
//console.log("+++++++++++++++++",cloudProperties[key]);
}
if (j == total_keys_cloudproperties) {
//console.log("inside break");
break;
}
}
console.log("After removing", cloudProperties);

Javascript looping through variables

So right now this is my current code and I'm trying to figure out a way to loop through the variables I've already declared (Assuming variables 1-9 already have values). I just wanted to know whether this was possible at all?
var title;
var brief;
var hover;
var whatTitle;
var whatDesc;
var whyTitle;
var whyDesc;
var funTitle;
var funDesc;
var titles = [];
var briefs = [];
var hovers = [];
var whatTitles = [];
var whatDescs = [];
var whyTitles = [];
var whyDescs = [];
var funTitles = [];
var funDescs = [];
var obj = {'titles' : title};
if(localStorage.getItem('titles') != null) {
var tmp = JSON.parse(localStorage.getItem('titles'));
for(var i = 0;i<tmp.length;i++) {
titles.push(tmp[i]);
}
}
titles.push(obj);
localStorage.setItem("titles", JSON.stringify(titles));
Output I want if we printed out the looped code:
var obj = {'titles' : title};
if(localStorage.getItem('titles') != null) {
var tmp = JSON.parse(localStorage.getItem('titles'));
for(var i = 0;i<tmp.length;i++) {
titles.push(tmp[i]);
}
}
titles.push(obj);
localStorage.setItem("titles", JSON.stringify(titles));
var obj = {'briefs' : brief};
if(localStorage.getItem('briefs') != null) {
var tmp1 = JSON.parse(localStorage.getItem('briefs'));
for(var i = 0;i<tmp.length;i++) {
briefs.push(tmp[i]);
}
}
briefs.push(obj);
localStorage.setItem("briefs", JSON.stringify(briefs));
var obj = {'hovers' : hover};
if(localStorage.getItem('hovers') != null) {
var tmp2 = JSON.parse(localStorage.getItem('hovers'));
for(var i = 0;i<tmp.length;i++) {
hovers.push(tmp[i]);
}
}
hovers.push(obj);
localStorage.setItem("hovers", JSON.stringify(hovers));
...etc
If the code is running in a browser, then you can do something like:
for(key in window) { console.log(window[key]) } // print all variables
The variables are associated to the global namespace. That is to say the upmost "this" reference or the window object.
You're almost there with the code you have. If you look at your "desired output" examples, you'll see that the only thing that really differs between each element of your "unrolled loop" is the key for local storage ('titles', 'briefs', 'hovers').
With that in mind, you could use an Object to map the keys to the variables you have at the top level. So this:
var titles = [];
var briefs = [];
var hovers = [];
var whatTitles = [];
var whatDescs = [];
...
Becomes (UPDATE: with the initializer values preserved):
var key_to_collection = {
'titles': [title],
'briefs': [brief],
'hovers': [hovers],
'whatTitles': [whatTitles],
'whatDescs': [whatDescs],
}
Then, you loop over the values of this object:
Object.keys(key_to_collection).forEach(function(key) {
var obj = {};
collection = key_to_collection[key];
obj[key] = collection;
if(localStorage.getItem(key) != null) {
var tmp = JSON.parse(localStorage.getItem(key));
for(var i = 0;i<tmp.length;i++) {
collection.push(tmp[i]);
}
}
collection.push(obj);
localStorage.setItem(key, JSON.stringify(collection));
});
If your variable name is title for example, then you can access it using window['title']. This means that if you define an array of your global variable names:
const varNames = ['title', 'brief', 'hover', ...]
Then you can do a loop like the following
for(const name of varNames) {
const value = window[name]
// do whatever you want using the variable name and value
}
I hope this solves your issue :)

Calling an array item into another array

I faced the following functions (or method I don't what is right name of the ):
function getRowArray($scope, object, i){
i = i + 1;
var item = {};
var data = [];
var id = -1;
if ($scope.selectedType !== undefined) {
id = $scope.selectedType.id;
}
var rating = getRating($scope, object, id);
item['name'] = $scope.objectInfo[object]['name'];
item['objectId'] = rating.objectId;
item['hideRating'] = parseInt($scope.objectInfo[object].hideControls) & 1;
item['addInfo'] = rating.addInfo;
item['rating'] = rating.value;
item['ratingId'] = rating.id;
for (var i in $scope.objectInfo[object].childs) {
if ($scope.objectInfo[object].childs[i] == object){
continue;
}
data.push(getRowArray($scope, $scope.objectInfo[object].childs[i], i));
}
item['data'] = data;
return item;
}
and
function getTypeRow($scope, oobject, otype){
var item = {};
var data = [];
var rating = getRating($scope, oobject.id, otype.id);
item['name'] = otype.name;
item['objectId'] = rating.objectId;
item['typeId'] = rating.typeId;
item['ratingId'] = rating.id;
item['addInfo'] = rating.addInfo;
item['rating'] = rating.value;
// item['hideRating'] = parseInt($scope.objectInfo[object].hideControls);
return item;
}
I want to use the hideRating item from the first one in the second, I tried and added the commented line but I got an error it says the object is undifined, is it wrong like that or am I missing something ? thanks in advance
object is undefined because it wasn't initialized; it's not specified in the parameter list for the function getTypeRow. The oobject in the parameter list should be corrected to object:
// Correct 'oobject' to 'object'
function getTypeRow($scope, object, otype){
var item = {};
var data = [];
// Correct 'oobject' to 'object'
var rating = getRating($scope, oobject.id, otype.id);
...
}

Merging arrays in JavaScript not working

When I try var a = ar_url2.concat(ar_desc2); to join my arrays into one it returns null. I'm sure it's trivial but I spent a few hours stuck on this now and an explanation as why this is happening would be great. In my code bellow I tried while(ar_url2.length)a.push(ar_url2.shift()); and it returns same null...
function agregar() {
var i = 0,
textarea;
var ar_desc = [];
while (textarea = document.getElementsByTagName('textarea')[i++]) {
if (textarea.id.match(/^desc_([0-9]+)$/)) {
ar_desc.push(textarea.id);
}
}
var desc_count_demo = document.getElementById('desc_count').value;
var desc_count = desc_count_demo - 1;
i = 0;
var ar_desc2 = [];
var campo = null;
while (i <= desc_count) {
campo = document.getElementById(ar_desc[i]).value;
ar_desc2[ar_desc[i]] = campo;
i++;
}
i = 0;
var input;
var ar_url = [];
while (input = document.getElementsByTagName('input')[i++]) {
if (input.id.match(/^url_([0-9]+)$/)) {
ar_url.push(input.id);
}
}
var url_count_demo2 = document.getElementById('url_count').value;
var url_count2 = url_count_demo2 - 1;
i = 0;
var ar_url2 = [];
while (i <= url_count2) {
campo = document.getElementById(ar_url[i]).value;
ar_url2[ar_url[i]] = campo;
i++;
}
// var a = Array.prototype.concat.call(ar_url2, ar_desc2);
while (ar_url2.length) a.push(ar_url2.shift());
function url(data) {
var ret = [];
for (var d in data)
ret.push(encodeURIComponent(d) + "=" + encodeURIComponent(data[d]));
return ret.join("&");
}
window.open('alta1.php?'+url(a));
}
EDIT: If I pass to function url(ar_url2) or url(ar_desc2) the returned values in the URL are
http://localhost/proj1/alta1.php?url_0=inpit&url_1=input
and
http://localhost/proj1/alta1.php?desc_0=input&desc_1=input
But still cannot merge both into one...
One thing I see is your ar_url Array is filled by:
while(input=document.getElementsByTagName('input')[i++]){
if(input.id.match(/^url_([0-9]+)$/)){
ar_url.push(input.id);
}
}
Since you the putting the whole id in the array, it will be filled with things like: 'url_0', 'url_1', 'url_2', etc...
Later you do:
ar_url2[ar_url[i]] = campo;
When you index into ar_url, you get out the 'url_XXX' strings. That means you are setting the 'url_XXX' properties on ar_url2 instead of filling in the elements of the array.
Try changing your second loop to:
while(input=document.getElementsByTagName('input')[i++]){
var result;
if(result = input.id.match(/^url_([0-9]+)$/)){
ar_url.push(+result[1]);
}
}
To use the value captured in the ([0-9]+) portion of the RegExp instead of the entire 'url_XXX' string.

Categories