How to dynamically include object value based on condition in Javascript? - javascript

Here is my objects
{"seatName": seats[i].name,
"fare": seats[i].fare,
"passenger": [{
"name":"",
"gender": "",
// "email":this.props.authStore.email,
// "mobile": this.props.authStore.phone
}]
}
Here, i need to include
"email":this.props.authStore.email,
"mobile": this.props.authStore.phone
When (i === 0), other than 0, for other these value should not be included ! How to achieve this ?
I tried like this :
(i === 0) ? "email": (i === 0) ? this.state.primaryUserEmail : "",
But it throws error !

Try using this :
...(i === 0 && {email: this.props.authStore.email}),
It will include when conditions satisfied and removes when not !

let data = {"seatName": "Joe",
"fare": 12,
"passenger": [{
"name":"",
"gender": "",
// "email":this.props.authStore.email,
// "mobile": this.props.authStore.phone
}]
}
/*
you can simply check if that passenger object has an email and mobile number and if they don't have you can then assign the number and email.
*/
if(!data.passenger[0]["email"]){
data.passenger[0]["email"] = "test#email.com";
}
if(!data.passenger[0]["mobile"]){
data.passenger[0]["mobile"] = 1234567890;
}
console.log(data)
/*
OUTPUT:
{
seatName: 'Joe',
fare: 12,
passenger: [ { name: '', gender: '', email: "test.email.com", mobile: 1234567890 } ]
}
*/

Related

How to filter an array of objects (with arrays inside) with another array of objects

I have these two arrays:
filters:
{
location: ['Swiss cottage','Fulham'],
age: ['Giga'],
}
and
data:
[
{
"location": "Swiss cottage",
"ages": "Giga",
},
{
"location": "Fulham",
"ages": "Kilo",
},
{
"location": "Putney",
"ages": "Micro",
}
]
I want to use the first one to filter the second, how should I do this?
You can do something like this. If it's either one of the filters, change && to ||.
let filters = {
location: ['Swiss cottage','Fulham'],
age: ['Giga'],
}
let data= [
{
"location": "Swiss cottage",
"ages": "Giga",
},
{
"location": "Fulham",
"ages": "Kilo",
},
{
"location": "Putney",
"ages": "Micro",
}
]
let x = data.filter(d => {
if (filters.location.includes(d.location) && filters.age.includes(d.ages))
return d;
});
console.log(x);
const filters = {
location: ['Swiss cottage','Fulham'],
age: ['Giga'],
};
const data = [
{
"location": "Swiss cottage",
"ages": "Giga",
},
{
"location": "Fulham",
"ages": "Kilo",
},
{
"location": "Putney",
"ages": "Micro",
}
];
const output = data.filter(item => {
return filters.location.indexOf(item.location) > -1 && filters.age.indexOf(item.ages) > -1;
});
console.log(output)
You could get the entries of filters for having an iterable data set and filter data by checking every key of the entries with the value.
As result you get only the object who match for all properties of the filter.
This approach requires the same property names for filter and data.
AND approach with Array#every
All searched properties must match.
var filters = { location: ['Swiss cottage', 'Fulham'], ages: ['Giga'] },
data = [{ location: "Swiss cottage", ages: "Giga" }, { location: "Fulham", ages: "Kilo" }, { location: "Putney", ages: "Micro" }],
entries = Object.entries(filters),
result = data.filter(o => entries.every(([k, v]) => v.includes(o[k])));
console.log(result);
OR approach with Array#some
One searched property must match.
var filters = { location: ['Swiss cottage', 'Fulham'], ages: ['Giga'] },
data = [{ location: "Swiss cottage", ages: "Giga" }, { location: "Fulham", ages: "Kilo" }, { location: "Putney", ages: "Micro" }],
entries = Object.entries(filters),
result = data.filter(o => entries.some(([k, v]) => v.includes(o[k])));
console.log(result);
It's simple, the arrays in the "filters" object need to include the corresponding values.
let filteredData = data.filter((x) =>
filters.location.includes(x.location) &&
filters.age.includes(x.ages));

Merge 2 object arrays in json files by key

I'm trying to combine 2 object array in javascript/jquery matching them by the same key (code). These object arrays are stored in 2 separate json files.
I've cut these down as the files are long
Thanks in advance if anyone can help.
Object 1:
[{
"city": "london",
"selfemployed": {
"job" :"Builder",
"code": "abc"
},
"company" : {
"job": "Shopkeeper",
"code": "def"
}
}]
Object 2:
[{
"code": "abc",
"participant": {
"firstname" : "Joe",
"lastname" : "Blogs"
}
},
{
"code": "def",
"participant": {
"firstname" : "Anna",
"lastname" : "Smith"
}
}]
Needed result:
[{
"city": "london",
"selfemployed": {
"job" :"Builder",
"code": "abc",
"participant": {
"firstname" : "Joe",
"lastname" : "Blogs"
}
},
"company" : {
"job": "Shopkeeper",
"code": "def",
"participant": {
"firstname" : "Anna",
"lastname" : "Smith"
}
}
}]
One of my issues is that I'm unable to return the object from the .json files
var file1 = 'url/file1.json';
var file1 = 'url/file2.json';
const joinJson = (file1, file2) => {
$.getJSON(file, function(data1) {
return data1;
});
$.getJSON(file2, function(data2) {
return data2;
});
// do stuff with data1 and data2
}
console.log(joinJson());
You could take a Map and build new objects for the result by selecting the wanted code information for the new object.
This proposal uses rest properties of an object with babel for older user agents.
var cities = [{ city: "london", selfemployed: { job: "Builder", code: "abc" }, company: { job: "Shopkeeper", code: "def" } }],
codes = [{ code: "abc", participant: { firstname: "Joe", lastname: "Blogs" } }, { code: "def", participant: { firstname: "Anna", lastname: "Smith" } }],
codesMap = new Map(codes.map(({ code, participant }) => [code, participant])),
result = cities.map(
({ city, ...items }) =>
Object.assign({ city }, ...Object.entries(items).map(
([k, v]) => ({ [k]: Object.assign({}, v, codesMap.get(v.code)) })
))
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
The problem is that you're getting the files asynchronously, and returning data in the callback of that async operation, which goes nowhere. Something like this would be better:
var file1 = 'url/file1.json';
var file1 = 'url/file2.json';
const joinJson = (file1, file2) => {
$.getJSON(file, function(data1) {
// async operation 1 complete. Start operation 2.
$.getJSON(file2, function(data2) {
// async operation 2 complete
// data1 and data2 are now available here
console.log("Data 1:", data1);
console.log("Data 2:", data2);
// This will merge the keys of both objects
// but you can replace it with custom merging logic
var merged = Object.assign(data1, data2);
console.log(merged);
});
});
}
The problem here is that you can't do something like console.log(joinJson());. You may very well need something like a Promise.

How to replace property without effecting data in javascript?

I have data in format like this:-
a.arr= [
0:{
name: abc,
dob: 18/12/1917,
panNo: ASDFG6789K
},
1:{
name: xyz,
dob: 1/2/1917,
panNo: WERTY6789K
}
]
I want to remove 0 and 1 and convert it in like this:-
a.arr= [
{
name: abc,
dob: 18/12/2017,
panNo: ASDFG6789K
},
{
name: xyz,
dob: 1/2/1917,
panNo: WERTY6789K
}
]
If I use delete then it removes the data as well inside object. Is there any other way to do this?
As some of the previous commenters said, your first code snippet does not contain valid JavaScript. However, if both the 0 and 1 become strings, as well as all of the values (abc, 18/12/1917, etc.), your data would look like this:
var a = {};
a.arr = [
{
"0": {
name: "abc",
dob: "18/12/1917",
panNo: "ASDFG6789K"
}
},
{
"1": {
name: "xyz",
dob: "1/2/1917",
panNo: "WERTY6789K"
}
}
];
To remove the 0 and 1, you could then do this:
var arr = a.arr.map(function(d){
var key = Object.keys(d)[0];
return d[key];
});
a.arr = arr;
// a.arr is now:
[{
"name": "abc",
"dob": "18/12/1917",
"panNo": "ASDFG6789K"
}, {
"name": "xyz",
"dob": "1/2/1917",
"panNo": "WERTY6789K"
}]

how to count similar value object in json?

I have this JSON structure:
[{
"name": "ankit",
"DOB": "23/06"
}, {
"name": "kapil",
"DOB": "26/06"
}, {
"name": "ankit",
"DOB": "27/06"
}]
I want to count similar object with value ankit. How can I do this?
You can use Array.prototype.filter():
var count = json.filter(function (el) {
return el.name == 'ankit';
}).length;
How about:
let a = [
{ "name": "ankit", "DOB": "23/06" },
{ "name": "kapil", "DOB": "26/06" },
{ "name": "ankit", "DOB": "27/06" }
];
let count = 0;
a.forEach(item => {
if (item.name === "ankit") {
count++;
}
});
(code in playground)
You could use an object for counting and get the wanted count for a name with the name as property.
var data = [{ "name": "ankit", "DOB": "23/06" }, { "name": "kapil", "DOB": "26/06" }, { "name": "ankit", "DOB": "27/06" }],
count = {};
data.forEach(function (a) {
count[a.name] = (count[a.name] || 0) + 1;
});
console.log(count);
console.log(count['ankit']);
You can use the reduce method to reduce the items that have the name ankit to a number.
var items = [
{
name: 'ankit',
DOB: '23/06'
},
{
name: 'kapil',
DOB: '26/06'
},
{
name: 'ankit',
DOB: '27/06'
}
]
var numItems = items.reduce(function (count, item) {
return item.name === 'ankit' ? count + 1 : count
}, 0)
document.write('Number of items with the name `ankit`: ' + numItems)
1. Get the object from JSON:
var obj = JSON.parse(text);
2. Get your array filtered:
var count = obj.filter(function(obj) { return obj.name == "ankit" }).length;

MongoDB $project embedded document to root level

Using the aggregate pipeline, I am trying to project an embedded document to the root level WITHOUT projecting each field individually.
For example, I want to project name from this collection to the root level:
[
{
_id: "1",
name: {
firstName: "John",
lastname: "Peters"
}
},
{
_id: "2",
name: {
firstName: "Mary",
lastname: "Jones"
}
}
]
This is what I am looking for:
[
{
firstName: "John",
lastname: "Peters"
},
{
firstName: "Mary",
lastname: "Jones"
}
]
Is there a way to do this without projecting each field individually? I don't want to have to do this:
db.collection.aggregate(
[
{
$project : {
"_id" : 0,
"firstName" : "$name.firstName",
"lastName" : "$name.lastName"
}
}
]
MongoDB 3.4 has the new stage in aggregation pipeline - $replaceRoot, which does exactly what was asked.
https://docs.mongodb.com/manual/reference/operator/aggregation/replaceRoot/
Here is the solution which uses JavaScript variable.
# Set Object for what to project
var projectWhat = {'_id' : 0};
# Fill Object with keys
Object.keys(db.coll.findOne().name).forEach(function(x){
projectWhat[x] = "$name." + x;
});
# Do Aggregate
db.coll.aggregate([{$project : projectWhat}])
And the output will be
{ "firstName" : "John", "lastname" : "Peters" }
{ "firstName" : "Mary", "lastname" : "Jones" }
Hope this helps.
You can use $replaceRoot like this:
db.collection.aggregate(
[
{
$replaceRoot : {
newRoot: {"$name"}
}
}
]
)
Also if you have a field in the root document you want to retain you can use a $mergeObjects to combine it with your embedded object:
db.collection.aggregate(
[
{
$replaceRoot : {
newRoot: {
$mergeObjects: [
{"_id": "$_id"},
"$name"
]
}
}
}
]
)
This may be achieved by using $set to update all documents with the values in the name sub-document:
db.collection.find({ "name": {"$exists": 1 } }).forEach(function(doc) {
var setName = {};
for ( var k in doc.name ) {
setName[k] = doc.name[k];
}
db.collection.update(
{ "_id": doc._id },
{ "$set": setName, "$unset": "name" }
);
})
While I'll recommend you use $project because it would be more performant than this solution, I can understand why you wouldn't want to use $project.
Starting Mongo 4.2, the $replaceWith aggregation operator can be used to replace a document by another (in our case by a sub-document):
// { _id: "1", name: { firstName: "John", lastname: "Peters" } }
// { _id: "2", name: { firstName: "Mary", lastname: "Jones" } }
db.collection.aggregate({ $replaceWith: "$name" })
// { firstName: "John", lastname: "Peters" }
// { firstName: "Mary", lastname: "Jones" }

Categories

Resources