In my loop i have a group id like this
****variable i value****
groupid 0 199
groupid 1 200
groupid 2 201
but in for loop its always take group 201 in first iteration why this happend. here is my code.
for (var i = 0; i < groupdata.length; i++) {
console.log('groupid', i, groupdata[i].id);
var groupname = groupdata[i].name;
var groupid = groupdata[i].id;
var groupType = groupdata[i].groupType;
var getuserdata = {
"groupID": groupdata[i].id,
"groupType": groupdata[i].groupType,
"token": req.usersession.token
};
var digest = BASE.utils.hmac("sha1", "A12AA418-1F28-4464-8B67-29CBD02BC45C-F048B14F-F3E3-4F97-A522-F2275A364A0E", JSON.stringify(getuserdata));
var postData = {
"groupID": groupdata[i].id,
"groupType": groupdata[i].groupType,
"digest": digest,
"token": req.usersession.token
};
var groupUserData = BASE.utils.base64encode(BASE.utils.base64encode(JSON.stringify(postData)));
BASE.request({
url: "http://example.com/getGroupUsers/",
method: "POST",
headers: {
"content-type": "application/json",
},
body: groupUserData
},
function(err, result, groupUserdata) {
var groupuserdata = JSON.parse(groupUserdata);
console.log('first groupusers.....', i, groupuserdata);
var groupids = groupuserdata.groupUsers.filter(function(group) {
if (group.userID != contactid) {
userbody.groups.map(function(usr) {
if (usr.id == groupid) {
console.log('maingroupid....', usr.id);
console.log('current loop groupid..', groupid);
group.groupData = usr;
}
return usr;
})
return group;
}
});
//console.log(groupids);
newgroupdta.push(groupids);
//res.send(groupids);
// console.log(groupids);
//console.log('.............',newgroupdta);
});
}
/* end for loop */
});
groupdata have below values
groupdata.... [ { groupType: '1',
id: '199',
unreadMessages: '0',
ownerId: '339',
name: 'xyz' }, { groupType: '1',
id: '200',
unreadMessages: '0',
ownerId: '339',
name: 'second group' }, { groupType: '1',
id: '201',
unreadMessages: '0',
ownerId: '339',
name: 'new one' } ]
groupusers data is like below
{ groupUsers: [ { userID: '0' }, { userID: '31' }, { userID: '326' } ] }
Basically i want to check contactid which is 326 exist in groupusers
if no then return that particular groupdata in array like
{groupdata:[{groupname:,groupid:}]}
/*********************edit***********************/
var count = 0;
var i =0;
function outer(data){
if(count==groupdata.length)break;
var groupname = groupdata[i].name;
var groupid = groupdata[i].id;
var groupType =groupdata[i].groupType;
var getuserdata = {
"groupID" :groupdata[i].id,
"groupType" : groupdata[i].groupType,
"token":req.usersession.token
};
var digest = BASE.utils.hmac("sha1", "A12AA418-1F28-4464-8B67-29CBD02BC45C-F048B14F-F3E3-4F97-A522-F2275A364A0E", JSON.stringify(getuserdata));
var postData = {
"groupID" :groupdata[i].id,
"groupType" : groupdata[i].groupType,
"digest" : digest,
"token" : req.usersession.token
};
var groupUserData = BASE.utils.base64encode(BASE.utils.base64encode(JSON.stringify(postData)));
BASE.request({
url : "http://201.206.158.254:8080/BACKSTAFF/service/getGroupUsers/",
method :"POST",
headers : {
"content-type": "application/json",
},
body :groupUserData
},
function (err,result,groupUserdata) {
console.log(groupUserdata);
});
i++;
outer(groupdata[count++]);
}
/***************end edit *************************/
You have written asynchronous callback function inside for loop .
As per your code above BASE.request({},function(){}) method will be called asynchronously , it will not wait for result and for loop will move to next .
There are multiple ways to handle this :
1) Async.js
2) Recursion ( Remove for and call next method from inside callback and at last break and come out of loop)
var count = 0;
function outer(data){
BASE.request({},function(){
if(count==groupdata.length)return;
//whatever logic
outer(groupdata[count++]);
})
}
3) Eventemitter can also be used
Related
I want to get all the values that equal a certain number and count how many of each of the objects.
My code looks like this:
var countItems = {
"aa":"70",
"bb":"70",
"cc":"80",
"dd":"90",
"ee":"90",
"ff":"90"
}
Now what I want to do is count each on that is in the second half.
For example, there are two "70", one "80", and three 90. Then I can assign to variables:
var firstCounter = ?? // 2
var secondCounter = ?? // 1
var thirdCounter = ?? // 3
?? is I don't know what goes here.
If it was structed differently like the following, I could do it like this:
let firstCounter = 0;
for (let i = 0; i < countItems.length; i++) {
if (countItems[i].status === '70') firstCounter++;
}
let secondCounter = 0;
for (let i = 0; i < countItems.length; i++) {
if (countItems[i].status === '80') secondCounter++;
}
let thirdCounter = 0;
for (let i = 0; i < countItems.length; i++) {
if (countItems[i].status === '90') thirdCounter++;
}
But the thing is, my original code which is what I have is not structured like that, so I'm not sure how to adapt it.
How can I count the items in the original list (var countItems) so that I can find out how much each value is?
You could use Object.values(countItems) to get an array that looks like this: ["70","70","80","90","90","90"] then either use a for loop to conditionally increment whatever counters you want, or use something like Array.reduce or Array.filter to count the elements you need.
You could use reduce to create a counted hash map like so:
const countItems = [
{ data: 'aa', status: '70' },
{ data: 'bb', status: '70' },
{ data: 'cc', status: '80' },
{ data: 'dd', status: '90' },
{ data: 'ee', status: '90' },
{ data: 'ff', status: '90' },
];
const countedHash = countItems.reduce((acc, curr) => {
if (!acc[curr.status])
acc[curr.status] = 1
else
acc[curr.status] += 1
return acc
}, {})
/* print out the results */
console.log(countedHash)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
You can access object keys like this :
countItems["aa"] // it will return "70"
You can also loop on the object (if you want to do as you did in your example) :
for (const item in countItems) {
console.log(countItems[item])
if (countItems[item] == "70") firstCounter++;
}
Object.values() and reduce() are both the right ideas. Taken together...
var countItems = {
"aa":"70",
"bb":"70",
"cc":"80",
"dd":"90",
"ee":"90",
"ff":"90"
};
let counts = Object.values(countItems).reduce((acc, value) => {
if (!acc[value]) acc[value] = 0;
acc[value]++;
return acc;
}, {});
let [theFirstValue, theSecondValue, theThirdValue] = Object.values(counts)
console.log(theFirstValue, theSecondValue, theThirdValue);
const countItems = [
{ data: 'aa', status: '70' },
{ data: 'bb', status: '70' },
{ data: 'cc', status: '80' },
{ data: 'dd', status: '90' },
{ data: 'ee', status: '90' },
{ data: 'ff', status: '90' },
];
var countValues = Object.values(countItems);
let obj ={}
for(let val of countValues){
if(!obj[val.status]){
obj[val.status] = 1
}else{
obj[val.status] += 1
}
}
console.log(obj)
I need to call transformResponse many times based persons array. But the following code call only the last index
function fill() {
var persons = [
{ id: 34, text: $translate.instant("enter") },
{ id: 36, text: $translate.instant("high") },
{ id: 53, text: $translate.instant("graduates") },
{ id: 35, text: $translate.instant("persons") },
]
var personSubCategoriesList = [];
for (var i = 0; i < persons.length; i++) {
$scope.remote = {
url: window.config.apiHostUrl + `lookup/Get?id=${persons[i].id}`,
transformResponse: function (data) {
var personSubCategories = angular.fromJson(data);
angular.forEach(personSubCategories, function (personSubCategoriesObjet) {
var categories = { name: personSubCategoriesObjet.localizedName, code: personSubCategoriesObjet.id };
personSubCategoriesList.push(categories);
});
return personSubCategoriesList.map(function (adminCategories) {
return {
name: adminCategories.name,
code: adminCategories.code
};
});
}
};
}
}
I found the solution by using observable $q
I execute the cycle and there is a line from the cycle that will match the specified parameters. The message "OK" should appear. Instead, I always get a result "No".
request(
{
url: 'http://localhost:5000/positions/get',
method: 'POST',
headers: headers
},
function (error, response, body) {
console.log('status: ' + response.statusCode)
if (response.statusCode) {
body = JSON.parse(body)
var formData = { Id: 75, Name: 'CEO' }
for (var i = 0; i < body.rows.length; i++ ) {
if (body.rows[i] === formData) {
console.log('Ок')
} else {
console.log('No')
}
}
}
}
)
Answer:
> console.log(body.rows)
[ { Id: 1, Name: 'Engineer' }, ..., ... 61 more items ]
if (body.rows[i] === formData) {
This line should be (if you want to check only Id)
if (body.rows[i].Id === formData.Id) {
or (if you want to check both Id and Name)
if (body.rows[i].Id === formData.Id && body.rows[i].Name === formData.Name ) {
As you can see
{ Id: 75, Name: 'CEO' } === { Id: 75, Name: 'CEO' } // return false
You should parse it to a string before compare because it's an object
JSON.stringify({ Id: 75, Name: 'CEO' }) === JSON.stringify({ Id: 75, Name: 'CEO' }) // true
the code should be
if (JSON.stringify(body.rows[i]) === JSON.stringify(formData)) {
console.log('Ок')
} else {
console.log('No')
}
Or you can use lodash for fast compare
_.isEqual(body.rows[i], formData)
I'm trying to make a simple ACL just for practice.
I want to loop through my object data and if my currentViewer has a parent I want to add his path (access in my object) to arrayAccess.
So if my viewer is user his accessArray should be ["", home], if he's admin it would be ["", home, user] and if he's a guest it will be only [""].
How to do it in a recursive way, so I don't have to create thousands of for loops?
I was trying calling a checkParent() inside my checkParent(), but it only makes my loop infinitive. I'm sorry if it's a silly question, I'm very beginning in JS.
var currentViewer = "user";
var data = {
users: [{
role: "guest",
access: ""
},
{
role: "user",
access: "home",
parent: "guest"
},
{
role: "admin",
access: "user",
parent: "user"
}
]
};
var accessArray = [];
function checkRole() {
var users = data.users;
for (var i = 0; i < users.length; i++) {
if (currentViewer === users[i].role) {
accessArray.push(users[i].access);
console.log(accessArray);
function checkParent() {
if (users[i].parent) {
for (var j = 0; j < users.length; j++) {
if (users[i].parent === users[j].role) {
accessArray.push(users[j].access);
console.log(accessArray);
}
}
}
};
checkParent();
}
};
};
checkRole();
You can try this:
var data = {
users : [
{ role:"guest" , access:"" },
{ role:"user" , access:"home", parent: "guest" },
{ role:"admin" , access:"user", parent: "user" }
]
};
var currentUser = "admin";
var arr = [];//array that you need
var defineAccess = function(item){
if(item.parent){
var index = data.users.map(function(e) { return e.role; }).indexOf(item.parent);
defineAccess(data.users[index]); //recursive calling
arr.push(data.users[index].access);
}
}
data.users.forEach(function(item){
if(currentUser === item.role){
arr.push(item.access);
defineAccess(item);
}
})
console.log(arr); //final output array
There are a bunch of ways to do it. Simple way is just make a hash for easy look up and reference the parents on a loop and push.
var data = { users : [
{ role:"guest" , access:"" },
{ role:"user" , access:"home", parent: "guest" },
{ role:"admin" , access:"user", parent: "user" }
]
};
var roleHash = data.users.reduce(function(o, i) {
o[i.role] = i;
return o;
}, {});
function getAccessRoles(roleKey) {
var role = roleHash[roleKey];
var roles = [role.access];
while (role.parent) {
role = roleHash[role.parent];
roles.unshift(role.access);
}
return roles;
}
console.log("admin", getAccessRoles("admin"));
console.log("user", getAccessRoles("user"));
console.log("guest", getAccessRoles("guest"));
I don't think "recursiveness" should be a goal on its own... Why not create a Map of roles and their properties and use the parent property to retrieve a new item from this map, until you can't?
var data = {
users: [{
role: "guest",
access: ""
},
{
role: "user",
access: "home",
parent: "guest"
},
{
role: "admin",
access: "user",
parent: "user"
}
]
};
var roles = new Map(data.users.map(u => [u.role, u]));
var getAccess = function(role) {
var access = [];
var current = roles.get(role);
while (current) {
access.push(current.access);
current = roles.get(current.parent);
}
return access.reverse();
}
console.log("guest", getAccess("guest"))
console.log("user", getAccess("user"))
console.log("admin", getAccess("admin"))
build an object model first,then the problem is simple.
var data = {
users: [
{
role: "guest",
access: ""
},
{
role: "user",
access: "home",
parent: "guest"
},
{
role: "admin",
access: "user",
parent: "user"
}
]
};
var users = data.users.reduce(function (roles, user) {
roles[user.role] = user;
return roles;
}, {});
var accessList = data.users.map(function (user) {
var all = [];
do {
all.unshift(user.access);
user = users[user.parent];
} while (user);
return all;
});
console.log(accessList);
I am trying to rebuild an array ,so I need suggestion on doing it using best practices.
I have an array object as follows:
MainObject:
0:"Namebar"
1: Object
Name: "Title1"
Url: "Url1"
2: Object
Name: "Title2"
Url: "Url2"
3: Object
Name: "Title3"
Url: "Url1"
In the above since the "url" is same , I want to group it same object and I am expecting the output in the following format:
0: "Url1"
1: Object
Name : "Title1"
Url: "Namebar"
2: Object
Name : "Title3"
Url: "Namebar"
1: "Url2"
1: Object
Name : "Title2"
Url: "Namebar"
I am trying to have two arrays and loop through the MainObject for swapping the items which I know is not only a teadious process but very much high on time complexity.
For example like :
var extract1 = MainObject[0];
var extract2 = using for loop to extract and swap ......
I am not getting any other way of achieving this. Any approach for this in javascript/jquery?
This should do the job:
var extract1 = MainObject[0];
var newArray = {};
var newArrProp;
var extract1Props = Object.keys(extract1);
for( i = 0; i< extract1Props.length; i++)
{
newArrProp = extract1Props[i];
var nestedObjects = extract1[newArrProp];
for(j = 0; j < nestedObjects.length; j++)
{
if(!newArray[nestedObjects[j].Url])
{
newArray[nestedObjects[j].Url] = [];
}
newArray[nestedObjects[j].Url].push({Name:nestedObjects[j].Name,Url:newArrProp});
}
}
Working fiddle
You could use some loops.
var MainObject = [{ "Namebar": [{ Name: "Title1", Url: "Url1" }, { Name: "Title2", Url: "Url2" }, { Name: "Title3", Url: "Url1" }] }],
object2 = [];
MainObject.forEach(function (a) {
Object.keys(a).forEach(function (k) {
a[k].forEach(function (b) {
var temp = {};
if (!this[b.Url]) {
temp[b.Url] = [];
this[b.Url] = temp[b.Url];
object2.push(temp);
}
this[b.Url].push({ name: b.Name, Url: k });
}, this);
}, this);
}, Object.create(null));
document.write('<pre>object2 ' + JSON.stringify(object2, 0, 4) + '</pre>');
document.write('<pre>MainObject ' + JSON.stringify(MainObject, 0, 4) + '</pre>');