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)
Related
I've got some JS data holding all kinds of data, numbers, child objects, arrays, etc in all manner of different structures:
let datapile = {
cover_img: { uid:'u2a3j4' },
avatar_img: { uid:'u5j3vg' },
created: 8273736384,
friends: [
{ name:'John', img: { uid:'u2726b' }, },
{ name:'Jane', parent: { profile_img: { uid:'u293k4' }, } },
],
occupation: {
past: current,
prior: {
title: 'Accountant',
company: {
logo: { img: { uid:'u29374' } },
}
},
},
...
}
And then I've got this JS list of images:
let imgs : [
{ uid:'u2a3j4', format:'jpg', alt_txt:'Lorem...', size:583729, dominant_color:'#d79273' },
{ uid:'u5j3vg', format:'png', alt_txt:'Lorem...', size:284849, dominant_color:'#f99383' },
{ uid:'u2726b', format:'gif', alt_txt:'Lorem...', size:293742, dominant_color:'#349a83' },
...
],
Now, what I need is a function I can call that will look through the datapile and append img data objects from the imgs list below. So where the datapile now has only the uid reference, it should have the entire img object. And I will then do the same with all kinds of other pieces of referenced data.
I've tried the following function:
function isArray(x){ return ( x !== undefined && Array.isArray(x) ) }
function isObject(x){ return (x && typeof x === "object" && !Array.isArray(x)) }
function get_item(type, uid) { /* loops through eg. imgs and returns img matching uid */ }
function append_referenced_relations(data){
if( !data ) return data
if( isObject(data) && data['uid'] !== undefined ) {
let item = get_item('any', data['uid'])
data = item
}
if( isObject(data) || isArray(data) ) {
for( let key in data ) {
data[key] = this.append_referenced_relations(deepClone(data[key]))
}
}
return data
}
... but I just can't get it to work. And my best googling efforts for similar scenarios have also come up empty. Can the internet help me out here?
you can try something like this
basically it use recursion and Object.fromEntries /entries to check all the keys of the inner object
if you have any specific question feel free to ask me
const decorate = (obj, data) => {
if (typeof obj !== 'object') {
return obj
}
if (Array.isArray(obj)) {
return obj.map(e => decorate(e, data))
}
return Object.fromEntries(
Object.entries(obj).flatMap(([k, v]) => {
if (k === 'uid') {
const imgData = data.find(d => v === d.uid)
return Object.entries(imgData || [[k, v]])
}
return [
[k, decorate(v, data)]
]
})
)
}
let datapile = {
cover_img: {
uid: 'u2a3j4'
},
avatar_img: {
uid: 'u5j3vg'
},
created: 8273736384,
friends: [{
name: 'John',
img: {
uid: 'u2726b'
},
},
{
name: 'Jane',
parent: {
profile_img: {
uid: 'u293k4'
},
}
},
],
occupation: {
past: 'current',
prior: {
title: 'Accountant',
company: {
logo: {
img: {
uid: 'u29374'
}
}
}
}
}
}
let imgs = [{
uid: 'u2a3j4',
format: 'jpg',
alt_txt: 'Lorem...',
size: 583729,
dominant_color: '#d79273'
},
{
uid: 'u5j3vg',
format: 'png',
alt_txt: 'Lorem...',
size: 284849,
dominant_color: '#f99383'
},
{
uid: 'u2726b',
format: 'gif',
alt_txt: 'Lorem...',
size: 293742,
dominant_color: '#349a83'
}
]
console.log(decorate(datapile, imgs))
You need to recurse in the nested datapile to identify the object with uids and add the img properties to be added.
Few cases to consider:
Objects. (If the Object has uid property, then stop recursion for its properties)
Object values having objects.
Array of Objects.
No need to return anywhere in your function actually as we can update objects inline.
Try like below.
let imgs = [ { uid: "u2a3j4", format: "jpg", alt_txt: "Lorem...", size: 583729, dominant_color: "#d79273", }, { uid: "u5j3vg", format: "png", alt_txt: "Lorem...", size: 284849, dominant_color: "#f99383", }, { uid: "u2726b", format: "gif", alt_txt: "Lorem...", size: 293742, dominant_color: "#349a83", }, { uid: "u293k4", format: "gif", alt_txt: "Lorem...", size: 193742, dominant_color: "#349a83", }, { uid: "u29374", format: "gif", alt_txt: "Lorem...", size: 793742, dominant_color: "#349a83", }, ]; let datapile = { cover_img: { uid: "u2a3j4" }, avatar_img: { uid: "u5j3vg" }, created: 8273736384, friends: [ { name: "John", img: { uid: "u2726b" } }, { name: "Jane", parent: { profile_img: { uid: "u293k4" } } }, ], occupation: { past: "current", prior: { title: "Accountant", company: { logo: { img: { uid: "u29374" } }, }, }, }, };
function isArray(x) {
return x !== undefined && Array.isArray(x);
}
function isObject(x) {
return typeof x === "object" && !Array.isArray(x);
}
function get_item(uid) {
return imgs.find((img) => img.uid === uid);
}
function append_referenced_relations(data) {
if (isObject(data)) {
if (data["uid"] !== undefined) {
const img = get_item(data.uid);
// Add img properties to the same object as properties
Object.entries(img).forEach(([key, value]) => {
data[key] = value;
});
} else {
// Recurse for the object values
Object.values(data).forEach((item) => {
append_referenced_relations(item);
});
}
} else if (isArray(data)) {
data.forEach((item) => {
// Recurse for the array entries
append_referenced_relations(item);
});
}
}
append_referenced_relations(datapile);
console.log(JSON.stringify(datapile, null, 2));
I have the following data in an array.
tempAttachments:Array[2]
0:Object
_id:"12345-678910"
bytes:412051
file:File
size:411532
title:"someFile.csv"
headers: Array[3]
0: optionOne
1: undefined
2: optionTwo
3: undefined
4: undefined
5: optionThree
type:"file"
fileType:"typeOne"
1:Object
_id:"9999-2222"
bytes:12345
file:File
size:23456
title:"anotherFile.csv"
headers: Array[3]
0: optionOne
type:"file"
fileType:"typeTwo"
There are two elements I am interested in, and that is the _id and headers array. I am trying to end up with something like this
Array
(
[0] => Array
(
[id] => 12345-678910
[optionOne] => 0
[optionTwo] => 2
[optionThree] => 5
)
[1] => Array
(
[id] => 9999-2222
[optionOne] => 0
)
)
So essentially, the id and the index of the three options as these relate to their column in a file. The problem is, a file may have a maximum of three options (using the names above) however, they may only have one or two.
So I have started like this
const payload = {}
this.tempAttachments.forEach(function (attachment, index) {
payload[index] = {
id: attachment._id
}
})
What I am unsure about is how to map the indexes of the options, with the key set as their name, if they exist. What would be the best way to achieve this?
Thanks
This is an environment/setting for a classic combined approach of map (here: create a new type from each attachment type) and reduce (here: create/collect new option data only for valid header/option items) ...
const tempAttachments = [{
_id: "12345-678910",
bytes: 412051,
file: "File",
size: 411532,
title: "someFile.csv",
headers: [
"optionOne",
undefined,
"optionTwo",
undefined,
undefined,
"optionThree"
],
type:"file",
fileType:"typeOne"
}, {
_id: "9999-2222",
bytes: 12345,
file: "File",
size: 23456,
title: "anotherFile.csv",
headers: [
"optionOne"
],
type: "file",
fileType: "typeTwo"
}];
function collectValidOptionData(collector, optionItem, idx) {
// if (optionItem != null) {
// collector[String(optionItem)] = idx
// }
if (typeof optionItem === 'string') {
collector[optionItem] = idx;
}
return collector;
}
function createOptionTypeFromAttachment(attachmentType) {
return attachmentType.headers.reduce(collectValidOptionData, {
id: attachmentType._id
});
}
console.log(
'tempAttachments.map(createOptionTypeFromAttachment) : ',
tempAttachments.map(createOptionTypeFromAttachment)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
A clean way to do this, is using the Array.map method, it creates a new array from another.
(More Info: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map)
The code below will convert the tempAttachments to the new format, where is based in this structure:
[
{
id: AttachmentID
optionName: optionIndex
optionName: optionIndex
...
}
]
It will only add options that have a value, ignoring undefined options.
Solution:
const payload = tempAttachments.map(attachment => {
const newAttachment = {
id: attachment._id,
}
attachment.headers.forEach((option, index) => {
if (option) {
newAttachment[option] = index;
}
})
return newAttachment;
})
Something like this:
const tempAttachments = [{
_id: "12345-678910",
bytes: 412051,
file: 'File',
size: 411532,
title: "someFile.csv",
headers: [
'optionOne',
undefined,
'optionTwo',
undefined,
undefined,
'optionThree'
],
type: "file",
fileType: "typeOne"
}, {
_id: "9999-2222",
bytes: 12345,
file: 'File',
size: 23456,
title: "anotherFile.csv",
headers: [
'optionOne',
'optionTwo',
'optionThree'
],
type: "file",
fileType: "typeTwo",
}];
const output = tempAttachments.reduce((akku, item) => {
let akkuItem = {
id: item._id,
};
item.headers.forEach((value, index) => {
if(typeof value !== 'undefined') {
akkuItem[value] = index;
}
});
akku.push(akkuItem);
return akku;
}, []);
console.log(output);
Open the page, get sexList and clientList form the server
Traverse 2 sets of data, push the sexText into the clientList
But the code is not working. How can I modify my code?
Code is here:
let sexList = [// store data: sexList
{
code: 0,
sexText: 'female',
},
{
code: 1,
sexText: 'male',
}
]
let clientList = [// index data: clientList
{
name: 'john',
sexCode: 1,
},
{
name: 'joe',
sexCode: 0,
}
]
mounted() {
this.$store.dispatch('getSexList')// get sexList form the server
getClientList({data: 'clients'}).then((res) => {
if(res.data.success) {
this.clientList = res.data.data// get clientList form the server
}else {
this.$message.error(res.data.message)
}
}).catch((err) => {
console.log(err)
})
},
watch: {
/*
watch clientList,traversing cientList and sexList,push the sexText into the clientList
*/
clientList(val) {
if(val && val.length > 0) {
val.map((item) {
this.$store.getters.sexList.map((sex_item) => {
if(sex_item.sexCode == item.sexCode) {
item.sexText = sex_item.sexText
}
})
})
}
},
}
After edit, it is working
setTimeout(() => {
getClientList({data: 'clients'}).then((res) => {
if(res.data.success) {
this.clientList = res.data.data// get clientList form the server
}else {
this.$message.error(res.data.message)
}
}).catch((err) => {
console.log(err)
})
}, 1000)
let clientList = [// index data: clientList
{
name: 'john',
sexCode: 1,
sexText: 'male',
},
{
name: 'joe',
sexCode: 0,
sexText: 'female',
}
]
Have another way?
I'm working on recursive functions.
I must push all objects that have the key "data: true" in an array.
The console.log in the middle of my function gives me all those objects in separate arrays.
But I can't return an array with the objects at the end.
What am I doing wrong?
Thanks
const entries = {
root: {
data: true,
key: "root",
text: "some text"
},
test: {
one: {
two: {
data: true,
key: "test.one.two",
text: "some text.again"
},
three: {
data: true,
key: "test.one.three",
text: "some.more.text"
}
},
other: {
data: true,
key: "test3",
text: "sometext.text"
}
},
a: {
b: {
data: true,
key: "a.b",
text: "a.b.text"
},
c: {
d: {
data: true,
key: "a.c.d",
text: "some.a.c.d"
}
}
}
};
function recursiveFunc(data) {
let tab = [];
for (let property in data) {
if (data.hasOwnProperty(property)) {
if (data[property].data === true) {
tab.push(data[property]);
console.log("t", tab);
} else {
recursiveFunc(data[property])
}
}
}
return tab
}
console.log(recursiveFunc(entries));
Add tab.concat() on the recursive call for join the items returned by the recursive fn.
const entries = {
root: {
data: true,
key: "root",
text: "some text"
},
test: {
one: {
two: {
data: true,
key: "test.one.two",
text: "some text.again"
},
three: {
data: true,
key: "test.one.three",
text: "some.more.text"
}
},
other: {
data: true,
key: "test3",
text: "sometext.text"
}
},
a: {
b: {
data: true,
key: "a.b",
text: "a.b.text"
},
c: {
d: {
data: true,
key: "a.c.d",
text: "some.a.c.d"
}
}
}
};
function recursiveFunc(data) {
let tab = [];
for (let property in data) {
if (data.hasOwnProperty(property)) {
if (data[property].data === true) {
tab.push(data[property]);
console.log("t", tab);
} else {
tab = tab.concat(recursiveFunc(data[property]));
}
}
}
return tab
}
console.log(recursiveFunc(entries));
You can pass an array as second argument that will act as an accumulator.
Plus, I fixed your function that loops infinitely when data = false:
function recursiveFunc(data, acc) {
for (let property in data) {
if (data.hasOwnProperty(property) && typeof data[property] === "object") {
var current = data[property];
if (current.data === true) {
acc.push(current);
} else {
recursiveFunc(current, acc)
}
}
}
}
Usage:
var results = [];
recursiveFunc(entries, results);
console.log(results);
You could use a global variable.
const entries = { ... };
var tab = [];
function getTab(data) {
tab = [];
recursiveFunc(data);
return tab;
}
function recursiveFunc(data) {
for (let property in data) {
if (data.hasOwnProperty(property) && typeof data[property] === "object") {
if (data[property].data === true) {
tab.push(data[property]);
} else {
recursiveFunc(data[property])
}
}
}
}
getTab(entries);
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