How know the value of property of object in javascript? - javascript

I have this object:
var x= {
"data": {
"getLand": {
"id": "xxx",
"bid": [{
"result": "ON",
"buyer": {
"username": "Dis"
},
"offerSet": [{
"createdStr": "202",
"value": 1
}]
},
{
"result": "CANCEL",
"buyer": {
"username": "Dis"
},
"offerSet": [{
"createdStr": "202",
"value": 15
}]
}
]
}
}
}
How can i know is result === "ON" && username == "Dis" ?
I tried with this:
for (var key in x.data.getLand.bid) {
if((x.data.getLand.bid[key].result === 'ON') && (x.data.getLand.bid[key].buyer.username.toUpperCase() === 'DIS')){
console.log(x.data.getLand.bid[key]);
}
}
it gives me some problems .... sometimes it works and sometimes it doesn't. Would you be kind enough to show me another way?

You can utilize the ES6 array function forEach to loop through the array items.
const x = { data: { getLand: { id: "xxx", bid: [ { result: "ON", buyer: { username: "Dis", }, offerSet: [ { createdStr: "202", value: 1, }, ], }, { result: "CANCEL", buyer: { username: "Dis", }, offerSet: [ { createdStr: "202", value: 15, }, ], }, ], }, }, }
const bidList = x.data.getLand.bid
bidList.forEach((bid, index) => {
if (bid.result === 'ON' && bid.buyer.username.toUpperCase() === 'DIS') console.log(index, bid)
})

You can do this with filter and forEach loop.
like this:
var x = { data: { getLand: { id: "xxx", bid: [ { result: "ON", buyer: { username: "Dis" }, offerSet: [{ createdStr: "202", value: 1 }] }, { result: "CANCEL", buyer: { username: "Dis" }, offerSet: [{ createdStr: "202", value: 15 }] } ] } } };
x.data.getLand.bid
.filter(
({ result, buyer: { username } }) => result === "ON" || username === "Dis"
)
.forEach((el, id) => console.log(el, id));

An example with for...of
var x = { data: { getLand: { id: "xxx", bid: [ { result: "ON", buyer: { username: "Dis", }, offerSet: [ { createdStr: "202", value: 1, }, ], }, { result: "CANCEL", buyer: { username: "Dis", }, offerSet: [ { createdStr: "202", value: 15, }, ], }, ], }, }, };
for (const item of x.data.getLand.bid) {
if (item.result === "ON" && item.buyer.username.toUpperCase() === "DIS") {
console.log(item);
}
}
Edit:
If you need the index, you can use forEach.
var x = { data: { getLand: { id: "xxx", bid: [ { result: "ON", buyer: { username: "Dis", }, offerSet: [ { createdStr: "202", value: 1, }, ], }, { result: "CANCEL", buyer: { username: "Dis", }, offerSet: [ { createdStr: "202", value: 15, }, ], }, ], }, }, };
x.data.getLand.bid.forEach((item, i) => {
if (item.result === "ON" && item.buyer.username.toUpperCase() === "DIS") {
console.log(i);
console.log(item);
}
});

Related

merge and remove elements in nested arrays

i have this array, i want to merge all elements inside the objects in the nested arrays and remove the duplicates..
the array is the output of mongo db populate so answers from there or just js will be amazing :)
"visitors": [
[
{
"name": "matan",
"id": "61793e6a0e08cdcaf213c0b1"
},
{
"name": "shani",
"id": "61793e910e08cdcaf213c0b5"
}
],
[
{
"name": "david",
"id": "6179869cb4944c6b19b05a23"
},
{
"name": "orit",
"id": "617986e535fdf4942ef659bd"
}
],
[
{
"name": "david",
"id": "6179869cb4944c6b19b05a23"
},
{
"name": "orit",
"id": "617986e535fdf4942ef659bd"
}
]
]
would like this output -
"visitors": [
{
"name": "matan",
"id": "61793e6a0e08cdcaf213c0b1"
},
{
"name": "shani",
"id": "61793e910e08cdcaf213c0b5"
},
{
"name": "david",
"id": "6179869cb4944c6b19b05a23"
},
{
"name": "orit",
"id": "617986e535fdf4942ef659bd"
},
]
these are my collections
i need to get all visitors on one solar system,
so > solars > planets > visitors
const solarsModel = new Schema({
planets: [ { type: Schema.Types.ObjectId ,ref:'planet'} ],
starName: { type: String, required: true, default: "" }
})
const planetModel = new Schema({
planetName: { type: String, required: true, default: "" },
system:{type: Schema.Types.ObjectId, ref: 'solar'},
visitors: [{ type: Schema.Types.ObjectId , ref: 'visitor'}]
})
const visitorModel = new Schema({
visitorName:{ type: String, required: true, default: "" },
homePlanet: {type: Schema.Types.ObjectId, ref:"planet" },
visitedPlanets: [{ type: Schema.Types.ObjectId, ref:"planet" }]
})
this is what i did to achieve a result would love to use Aggregate..
const response = await solarModel
.findById({ _id: data.id })
.select({ starName: 1, _id: 0 })
.populate({
path: "planets",
select: { visitors: 1, _id: 0 },
populate: {
path: "visitors",
select: "visitorName",
},
})
.exec();
solved with this
exports.findVisitorSystemHandler = async (data) => {
const systemName = await solarModel.findById({ _id: data.id });
const response = await planetModel.aggregate([
{ $match: { system: makeObjectId(data.id) } },
{
$lookup: {
from: "visitors",
localField: "visitors",
foreignField: "_id",
as: "solarVisitors",
},
},
{
$project: {
solarVisitors: {
visitedPlanets: 0,
homePlanet: 0,
__v: 0,
},
},
},
{ $unwind: "$solarVisitors" },
{
$group: {
_id: null,
system: { $addToSet: systemName.starName },
solarVisitors: {
$addToSet: {
id: "$solarVisitors._id",
name: "$solarVisitors.visitorName",
},
},
},
},
{ $unwind: "$system" },
{
$project: {
_id: 0,
},
},
]);
return response;
};
You can use aggregate() like this:
$unwind twice due to nested array
$group using $addToSet to not get duplicates.
db.collection.aggregate([
{
"$unwind": "$visitors"
},
{
"$unwind": "$visitors"
},
{
"$group": {
"_id": null,
"visitors": {
"$addToSet": {
"id": "$visitors.id",
"name": "$visitors.name"
}
}
}
}
])
Example here
(1) Flatten the array of arrays
visitors = visitors.flat();
Which gives us this:
[
{ name: 'matan', id: '61793e6a0e08cdcaf213c0b1' },
{ name: 'shani', id: '61793e910e08cdcaf213c0b5' },
{ name: 'david', id: '6179869cb4944c6b19b05a23' },
{ name: 'orit', id: '617986e535fdf4942ef659bd' },
{ name: 'david', id: '6179869cb4944c6b19b05a23' },
{ name: 'orit', id: '617986e535fdf4942ef659bd' }
]
(2) Get unique ids
let uniqueIds= [...new Set(visitors.map(v => v.id)]
Which gives us this:
[
'61793e6a0e08cdcaf213c0b1',
'61793e910e08cdcaf213c0b5',
'6179869cb4944c6b19b05a23',
'617986e535fdf4942ef659bd'
]
(3) Get new list of visitors based only on uniqueIds
visitors = uniqueIds.map(id => {
let name = visitors.find(v => v.id === id).name;
return {
id,
name
}
});
Which gives us this:
[
{ name: 'matan', id: '61793e6a0e08cdcaf213c0b1' },
{ name: 'shani', id: '61793e910e08cdcaf213c0b5' },
{ name: 'david', id: '6179869cb4944c6b19b05a23' },
{ name: 'orit', id: '617986e535fdf4942ef659bd' },
]
Query
reduce with concat to flatten
union with an empty array,just to remove duplicates
if you have other fields except visitors they are not affected
PlayMongo
aggregate(
[{"$set":
{"visitors":
{"$setUnion":
[{"$reduce":
{"input": "$visitors",
"initialValue": [],
"in": {"$concatArrays": ["$$value", "$$this"]}}},
[]]}}}])
Results
[{
"visitors": [
{
"name": "david",
"id": "6179869cb4944c6b19b05a23"
},
{
"name": "matan",
"id": "61793e6a0e08cdcaf213c0b1"
},
{
"name": "orit",
"id": "617986e535fdf4942ef659bd"
},
{
"name": "shani",
"id": "61793e910e08cdcaf213c0b5"
}
]
}]

how to apply recursive function on json data in javascript

I've validation schema in js like this
var data = [
{
id: {
label: "",
tests: [
{
name: "required",
params: "",
},
],
},
},
{
name: {
fields: {
firstName: {
label: "",
tests: [
{
name: "required",
params: "",
},
],
},
lastName: {
label: "",
tests: [
{
name: "required",
params: "",
},
],
},
midName: {
label: "",
tests: [],
},
},
tests: [],
},
},
{
email: {
label: "",
tests: [
{
name: "required",
params: "",
},
],
},
},
{
city: {
label: "",
tests: [],
},
},
{
details: {
fields: {
age: {
label: "",
tests: [
{
name: "max",
params: {
max: 18,
},
},
],
},
tests: [],
},
},
},
];
I only want the name of the keys from array which has required field like this
var selected= ["id", "name", "email"].
For this want to create one dynamic function like if data has key:"tests" 'required' it will return the name and if data has key:"fields" it will check again for the 'tests'.
var data = [
{
id: {
label: "",
tests: [
{
name: "required",
params: "",
},
],
},
},
{
name: {
fields: {
firstName: {
label: "",
tests: [
{
name: "required",
params: "",
},
],
},
lastName: {
label: "",
tests: [
{
name: "required",
params: "",
},
],
},
midName: {
label: "",
tests: [],
},
},
tests: [],
},
},
{
email: {
label: "",
tests: [
{
name: "required",
params: "",
},
],
},
},
{
city: {
label: "",
tests: [],
},
},
{
details: {
fields: {
age: {
label: "",
tests: [
{
name: "max",
params: {
max: 18,
},
},
],
},
tests: [],
},
},
},
]
console.clear()
const keys = data.map(x => recursive(Object.keys(x)[0], x)).filter(x => x !== undefined)
function recursive (name, x) {
for (let key in x) {
if (x[key].tests !== undefined && typeof x[key].tests === "object") {
const find = x[key].tests.find(y => y.name === "required")
if (find) return name
}
if (x[key].fields !== undefined) {
for (let y in x[key].fields) {
if (y !== "tests") {
console.log(y)
const v = recursive(parent, x[key].fields)
if (v !== undefined) return name
}
}
}
}
}
console.log("KEYS", keys)
Like you said search recursive in child if we have only one time require in namefield. Just you need to remember the name of your data and filter at the end, because i don't return a name so that return undefined if i didn't find this specific string field.

How to sort/order multiple objects inside array?

This is my output:
const data = {
item : {
id: "1",
name: "aa",
group: [
{
id:"11",
order:0,
},
{
id:"33",
order:5,
},
{
id:"3",
order:1,
},
]
},
item2 : {
id: "2",
name: "aaa",
group: [
{
id:"111",
order:3,
},
{
id:"33",
order:1,
},
{
id:"3",
order:2,
},
]
}
}
I want to order my group object by order item. If it was an object, I could do it:
data.group.sort((a, b) => {
return a.order - b.order || a.order.localeCompare(b.order);
});
But it will override the elements and I will get only the lastest item. I believe that something else is missing to make it work the way I want.
This is the desired output:
const data = {
item : {
id: "1",
name: "aa",
group: [
{
id:"11",
order:0,
},
{
id:"3",
order:1,
},
{
id:"33",
order:5,
},
]
},
item2 : {
id: "2",
name: "aaa",
group: [
{
id:"33",
order:1,
},
{
id:"3",
order:2,
},
{
id:"111",
order:3,
},
]
}
}
How can i do that?
Try this code:
const data = {
item : {
id: "1",
name: "aa",
group: [
{
id:"11",
order:0,
},
{
id:"33",
order:5,
},
{
id:"3",
order:1,
},
]
},
item2 : {
id: "2",
name: "aaa",
group: [
{
id:"111",
order:3,
},
{
id:"33",
order:1,
},
{
id:"3",
order:2,
},
]
}
}
Object.keys(data).forEach(key => {
const item = data[key];
item.group = item.group.sort((a, b) => {
return a.order - b.order || a.order.localeCompare(b.order);
});
return item;
});
console.log(data);
Do this (CREDIT TO: flymaster)
Object.keys(dataINPT).forEach(key => {
const your = dataINPT[key];
your.group = your.group.sort((some, some2) => {
return some.order - some2.order || some.order.localeCompare(some2.order);
});
return your;
});
console.log(data);
Use the Object.values, forEach loop and apply sort.
Object.values(data).forEach(({ group }) =>
group.sort((a, b) => {
return a.order - b.order || a.order.localeCompare(b.order);
})
);
const data = {
item: {
id: "1",
name: "aa",
group: [
{
id: "11",
order: 0,
},
{
id: "33",
order: 5,
},
{
id: "3",
order: 1,
},
],
},
item2: {
id: "2",
name: "aaa",
group: [
{
id: "111",
order: 3,
},
{
id: "33",
order: 1,
},
{
id: "3",
order: 2,
},
],
},
};
Object.values(data).forEach(({ group }) =>
group.sort((a, b) => {
return a.order - b.order || a.order.localeCompare(b.order);
})
);
console.log(data);

How to filtering between array of sub arrays and array of sub arrays in javascript?

I have got two arrays of objects. I want to filter data based on PermissionObj.
This is coming from database. Here are arrays of sub-arrays in the permissionObj.
const PermissionObj = {
permission: [
{
books: [
{
label: "Can View",
value: "can_view"
}
]
},
{
Journals: [
{
label: "Can View",
value: "can_view"
},
{
label: "Can Create",
value: "can_create"
}
]
},
{
deal: [
{
label: "Can update",
value: "can_update"
},
{
label: "Can delete",
value: "can_delete"
}
]
}
]
}
this is static data. I want to compare this data based on PermissionObj.
const data = [
{
label: "books",
value: "can_view"
},
{
label: "deal",
content: [
{
value: "can_update"
},
{
value: "can_delete"
},
{ value: "can_view" }
]
},
{
label: "Articles"
},
{
label: "Journals",
content: [
{
value: "can_create"
},
{
value: "can_view"
},
{
value: "can_delete"
},
{
value: "can_edit"
}
]
}
]
I am trying to filter the data array of the object based on PermissionObj array of objects. here is my trying code.
const permKeys = PermissionObj.permission.flatMap(item => Object.keys(item));
const filteredData = data.filter(({ label }) => permKeys.includes(label));
console.log(filteredData);
Here is my problem, I have been faced is that I don't want to get can_edit, can_delete if it doesn't match with permission objects in journals. In my permission objects, There is no can_edit and can_delete in journals.
My accepted Output would be this format :
const data = [
{
label: "books",
value: "can_view"
},
{
label: "deal",
content: [
{
value: "can_update"
},
{
value: "can_delete"
}
]
},
{
label: "Journals",
content: [
{
value: "can_create"
},
{
value: "can_view"
}
]
}
]
It is possible to use reduce method and apply logic to decide what data should be pushed:
const result = data.reduce((a, c) => {
let filterObj = PermissionObj.permission.find(f => f[c.label]);
if (filterObj) {
if (c.value) {
a.push(c);
}
if (c.content) {
c.content = c.content.filter(f => filterObj[c.label]
.some(s => s.value.toLowerCase() == f.value.toLowerCase()));
a.push(c);
}
}
return a;
},[])
An example:
const PermissionObj = {
permission: [
{
"books": [
{
"label": "Can View",
"value": "can_view"
}
]
},
{
"Journals": [
{
"label": "Can View",
"value": "can_view"
},
{
"label": "Can Create",
"value": "can_create"
}
]
},
{
"deal": [
{
"label": "Can update",
"value": "can_update"
},
{
"label": "Can delete",
"value": "can_delete"
}
]
}
]
};
const data = [
{
label: "books",
value: "can_view"
},
{
label: "deal",
content: [
{
value: "can_update"
},
{
value: "can_delete"
},
{
value:"can_view"
}
]
},
{
label: "Articles",
},
{
label: "Journals",
content: [
{
value: "can_create"
},
{
value: "can_view"
},
{
value: "can_delete"
},
{
value: "can_edit"
}
]
}
];
const result = data.reduce((a, c) => {
let filterObj = PermissionObj.permission.find(f => f[c.label]);
if (filterObj) {
if (c.value) {
a.push(c);
}
if (c.content) {
c.content = c.content.filter(f => filterObj[c.label].some(s => s.value.toLowerCase() == f.value.toLowerCase()));
a.push(c);
}
}
return a;
},[])
console.log(result);

Setting array keys dynamically based on length

Given an array in this format:
[
[{
name: "name",
value: "My-name"
},
{
name: "qty",
value: "1"
},
{
name: "url",
value: "test.com"
},
{
name: "comment",
value: "my-comment"
}
],
[{
name: "name",
value: "My-name2"
},
{
name: "qty",
value: "3"
},
{
name: "url",
value: "test2.com"
}
],
[{
name: "name",
value: "My-name3"
},
{
name: "qty",
value: "1"
},
{
name: "url",
value: "test3.com"
},
{
name: "comment",
value: "my-comment3"
}
]
]
I'm looking to switch that to:
[
[
{ name: "My-name" },
{ qty: "1" },
{ url: "test.com" },
{ comment: "my-comment", }
],[
{ name: "My-name2" },
{ qty: "3" },
{ url: "test2.com",
],[
{ name: "My-name3", },
{ qty: "1", },
{ url: "test3.com", },
{ comment: "my-comment3", }
]
]
In other words, swapping out the array keys but maintaining the object structure within each array element.
I've tried looping over each element and can swap the keys out using something like:
newArray[iCount][item.name] = item.value;
However I'm then struggling to preserve the object order. Note that the comment field may or may not appear in the object.
With Array.map() function:
var arr = [
[{name:"name",value:"My-name"},{name:"qty",value:"1"},{name:"url",value:"test.com"},{name:"comment",value:"my-comment"}],
[{name:"name",value:"My-name2"},{name:"qty",value:"3"},{name:"url",value:"test2.com"}],
[{name:"name",value:"My-name3"},{name:"qty",value:"1"},{name:"url",value:"test3.com"},{name:"comment",value:"my-comment3"}]
],
result = arr.map(function(a){
return a.map(function(obj){
var o = {};
o[obj.name] = obj.value
return o;
});
});
console.log(result);
Check my moreBetterOutput value. I think will be better.
If you still need a result like your example in the question then you can check output value.
const input = [
[
{
name:"name",
value:"My-name"
},
{
name:"qty",
value:"1"
},
{
name:"url",
value:"test.com"
},
{
name:"comment",
value:"my-comment"
}
],
[
{
name:"name",
value:"My-name2"
},
{
name:"qty",
value:"3"
},
{
name:"url",
value:"test2.com"
}
],
[
{
name:"name",
value:"My-name3"
},
{
name:"qty",
value:"1"
},
{
name:"url",
value:"test3.com"
},
{
name:"comment",
value:"my-comment3"
}
]
]
const output = input.map(arr => arr.map(obj => ({[obj.name]: obj.value})))
const moreBetterOutput = output.map(arr => arr.reduce((acc, item, index) => {
acc[Object.keys(item)[0]] = item[Object.keys(item)[0]];
return acc;
}, {}) )
//console.log(output);
console.log(moreBetterOutput);
Another map function:
const result = array.map( subarray =>
Object.assign(...subarray.map( ({name, value}) => ({ [name] : value }) ))
);

Categories

Resources