My array:
[
{
name: 'test1',
state: 'OK',
status: true,
pending: 33,
approved: 0,
active: 0,
inactive: 33
},
{
name: 'test3',
state: 'OK',
status: true,
pending: 33,
approved: 0,
active: 0,
inactive: 33
},
{
name: 'test4',
state: 'OK',
status: true
}
]
If the "pending", "approved", "active", "inactive" key not exists in object, i need output like this:
Expected output:
[
{
name: 'test1',
state: 'OK',
status: true,
pending: 33,
approved: 0,
active: 0,
inactive: 33
},
{
name: 'test3',
state: 'OK',
status: true,
pending: 33,
approved: 0,
active: 0,
inactive: 33
},
{
name: 'test4',
state: 'OK',
status: true,
pending: 0,
approved: 0,
active: 0,
inactive: 0
}
]
How to do this?
I tried with map but i dont know how to set condition.
I want to set the values into zero.
You can use Array.map() and use an array of properties, iterate over the array of properties and check for each object if that property is present in the object or not, if it is not present than simply add the property and assign it value as 0.
let arr = [ { name: 'test1', state: 'OK', status: true, pending: 33, approved: 0, active: 0, inactive: 33 }, { name: 'test3', state: 'OK', status: true, pending: 33, approved: 0, active: 0, inactive: 33 }, { name: 'test4', state: 'OK', status: true } ];
let props = ['active','inactive', 'approved', 'pending'];
let result = arr.map(a =>{
props.forEach(prop=> a[prop] = a[prop] || 0);
return a;
});
console.log(result);
You can use .forEach to apply your condition to each object.
arr = [
{
name: 'test1',
state: 'OK',
status: true,
pending: 33,
approved: 0,
active: 0,
inactive: 33
},
{
name: 'test3',
state: 'OK',
status: true,
pending: 33,
approved: 0,
active: 0,
inactive: 33
},
{
name: 'test4',
state: 'OK',
status: true
}
]
arr.forEach(obj => {for (let p of ['pending', 'approved', 'active', 'inactive']){
if (!obj.hasOwnProperty(p)){
obj[p] = 0;
}
}});
console.log(arr);
Create an object having properties with their default values.
Use .map() to iterate over objects of the given array by passing a callback.
Use Object.assign() method to create a close of the current object by passing an empty object, default object and current object as arguments. First defaults values will be copied into empty object and then Object.assign() will copy each property from the current object in the cloned effectively overriding the default values.
Below is a demo:
let data = [
{name: 'test1',state:'OK',status:true,pending: 33,approved: 0,active: 0,inactive: 33},
{name: 'test3',state:'OK',status:true,pending: 33,approved: 0,active: 0,inactive: 33},
{name: 'test4',state:'OK',status:true}
];
let defaults = {
pending: 0,
approved: 0,
inactive: 0,
active: 0
};
let result = data.map(o => Object.assign({}, defaults, o));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Resources:
Array.prototype.map()
Object.assign()
Related
I am currently working with an object and trying to extract the highest value of duration field. I am trying to use both flatMap and Math.max to achieve this but so far I am getting a -Infinity result. I am also calling this flatMap twice which is likely not right :/. What would be the right approach to get the highest value of duration?
const users = [{
name: 'User1',
configuration: [{
email: 'test1#email.com',
duration: 60,
active: true
},
{
email: 'test2#email.com',
duration: 180,
active: false
}
],
},
{
name: 'User2',
configuration: [{
email: 'test3#email.com',
duration: 120,
active: true
},
{
email: 'test4#email.com',
duration: 30,
active: true
}
],
},
{
name: 'User3',
configuration: [{
email: 'test5#email.com',
duration: 300,
active: true
},
{
email: 'test6#email.com',
duration: 10,
active: true
}
],
},
];
Code:
const x = users.flatMap(user => user.configuration);
const y = x.flatMap(user => user.duration);
const highestvalue = Math.max(...Object.values(y).flat().flatMap(Object.values));
console.log(highestvalue);
Current Result:
-Infinity
Desired Result:
300
With your current code, your y array contains the list of destination values. You can use Math.max(...y) to get the max number from that array. While you're calling .flatMap() twice, you only need to call it once on your original users array to flatten the objects within your configuration arrays into one resulting array. Once you have these objects flattened you don't need to call it again when you map x and instead can use just .map():
const users = [{ name: 'User1', configuration: [{ email: 'test1#email.com', duration: 60, active: true }, { email: 'test2#email.com', duration: 180, active: false } ], }, { name: 'User2', configuration: [{ email: 'test3#email.com', duration: 120, active: true }, { email: 'test4#email.com', duration: 30, active: true } ], }, { name: 'User3', configuration: [{ email: 'test5#email.com', duration: 300, active: true }, { email: 'test6#email.com', duration: 10, active: true } ], }, ];
const x = users.flatMap(user => user.configuration);
const y = x.map(user => user.duration);
console.log(Math.max(...y));
You can also simplify by removing the intermediate variables by mapping each object which each configuration array to its duration, and which then gets flattened into one resulting array due to the outer .flatMap():
const users = [{ name: 'User1', configuration: [{ email: 'test1#email.com', duration: 60, active: true }, { email: 'test2#email.com', duration: 180, active: false } ], }, { name: 'User2', configuration: [{ email: 'test3#email.com', duration: 120, active: true }, { email: 'test4#email.com', duration: 30, active: true } ], }, { name: 'User3', configuration: [{ email: 'test5#email.com', duration: 300, active: true }, { email: 'test6#email.com', duration: 10, active: true } ], }, ];
const highest = Math.max(...users.flatMap(
user => user.configuration.map(({duration}) => duration)
));
console.log(highest);
Note, as #Chris_F pointed out, if you expect your array to be large or are unsure of the size of your array, then you may potentially run into the max argument limitation when trying to spread your array elements into Math.max(). In this case, you can use a loop to find the max value (rather than spreading the arrary elements), below I've used .reduce():
const max = arr => arr.reduce((m, c) => Math.max(m, c), -Infinity);
const users = [{ name: 'User1', configuration: [{ email: 'test1#email.com', duration: 60, active: true }, { email: 'test2#email.com', duration: 180, active: false } ], }, { name: 'User2', configuration: [{ email: 'test3#email.com', duration: 120, active: true }, { email: 'test4#email.com', duration: 30, active: true } ], }, { name: 'User3', configuration: [{ email: 'test5#email.com', duration: 300, active: true }, { email: 'test6#email.com', duration: 10, active: true } ], }, ];
const highest = max(users.flatMap(
user => user.configuration.map(({duration}) => duration)
));
console.log(highest);
Say I have a data structure like so.
child: [
{
typeOfPackage: 'subSub',
parents: '/Test123/Diet/',
itemName: '250 ML',
pricePerItem: 150,
quantity: 0,
quantityType: '123',
description: '5',
avgTimeTaken: 0,
images: [],
isEnabled: true,
inventory: [],
equipment: [],
_id: 617f9efdf0347931684888fd
},
{
typeOfPackage: 'sub',
parents: '/Test123/',
itemName: 'Regular',
pricePerItem: 0,
quantity: 0,
quantityType: '1',
description: '1',
avgTimeTaken: 1,
images: [],
isEnabled: true,
inventory: [],
equipment: [],
_id: 617f9efdf0347931684888fe
},
{
typeOfPackage: 'subSub',
parents: '/Test123/Reg3/',
itemName: '500ML',
pricePerItem: 123,
quantity: 0,
quantityType: '12',
description: '123',
avgTimeTaken: 51,
images: [],
isEnabled: true,
inventory: [],
equipment: [],
_id: 617f9efdf0347931684888ff
}
]
I intend to transform this data by splitting parents. And my intended result looks as follows:
child: [
{
itemName: 'Test123',
subPackages: [
{
itemName: 'Diet',
subSubPackages: [{
typeOfPackage: 'subSub',
parents: '/Test123/Diet/',
itemName: '250 ML',
pricePerItem: 150,
quantity: 0,
quantityType: '123',
description: '5',
avgTimeTaken: 0,
images: [],
isEnabled: true,
inventory: [],
equipment: [],
}]
},
{
itemName: 'Regular',
typeOfPackage: 'sub',
parents: '/Test123/',
pricePerItem: 0,
quantity: 0,
quantityType: '1',
description: '1',
avgTimeTaken: 1,
images: [],
isEnabled: true,
inventory: [],
equipment: [],
subSubPackages: [],
},
{
itemName: 'Reg3',
subSubPackages: [
{
typeOfPackage: 'subSub',
parents: '/Test123/Reg3/',
itemName: '500ML',
pricePerItem: 123,
quantity: 0,
quantityType: '12',
description: '123',
avgTimeTaken: 51,
images: [],
isEnabled: true,
inventory: [],
equipment: [],
_id: 617f9efdf0347931684888ff
}
]
},
]
}
]
I tried using lodash's chain and groupBy but I could only get as far as grouping it by the first itemName (Test123). I could not figure out how to do further grouping inside that without using a custom for loop and map methods and that too confused me.
You could split parents and build a nested structure.
This approach takes an shadow object for a faster access to same named parents and returns only the payload without organizing structure.
If you like to use subPackages or subSubPackages, you could take a function for generating this key along with the actuyl nesting level. For later processing data, I recommend to use only generic names, like children for every level.
const
getSub = level => `sub${'Sub'.repeat(level)}Level`,
data = [{ typeOfPackage: 'subSub', parents: '/Test123/Diet/', itemName: '250 ML', pricePerItem: 150, quantity: 0, quantityType: '123', description: '5', avgTimeTaken: 0, images: [], isEnabled: true, inventory: [], equipment: [], _id: '617f9efdf0347931684888fd' }, { typeOfPackage: 'sub', parents: '/Test123/', itemName: 'Regular', pricePerItem: 0, quantity: 0, quantityType: '1', description: '1', avgTimeTaken: 1, images: [], isEnabled: true, inventory: [], equipment: [], _id: '617f9efdf0347931684888fe' }, { typeOfPackage: 'subSub', parents: '/Test123/Reg3/', itemName: '500ML', pricePerItem: 123, quantity: 0, quantityType: '12', description: '123', avgTimeTaken: 51, images: [], isEnabled: true, inventory: [], equipment: [], _id: '617f9efdf0347931684888ff' }],
result = data
.reduce((r, o) => {
o
.parents
.split('/')
.filter(Boolean)
.reduce((t, itemName, i) => {
if (!t[itemName]) {
t[itemName] = { _: [] };
t._.push({ itemName, [getSub(i)]: t[itemName]._ });
}
return t[itemName];
}, r)
._
.push(o);
return r;
}, { _: [] })
._;
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I'm new to js and react js with redux i'm trying to update a value of the global state immutably This is my current state
const initialState = {
questions: [
{
id: 1010,
name: "Inside which HTML element do we put the JavaScript?",
questionTypeId: 1,
options: [
{
id: 10,
name: "javascript",
isAnswer: false,
isSelected: false
},
{
id: 11,
name: "scripting",
isAnswer: false,
isSelected: false
},
{
id: 12,
name: "script",
isAnswer: true,
isSelected: false
},
{
id: 13,
name: "js",
isAnswer: false,
isSelected: false
}
]
},
{
id: 1011,
name: "Javascript is a langague used for ?",
questionTypeId: 2,
options: [
{
id: 14,
name: "ConsoleApp",
isAnswer: false,
isSelected: false
},
{
id: 15,
name: "ShellApp",
isAnswer: false,
isSelected: false
},
{
id: 16,
name: "WebApp",
isAnswer: true,
isSelected: false
},
{
id: 17,
name: "MobileApp",
isAnswer: false,
isSelected: false
}
]
},
{
id: 1012,
name: "What is the full form of SPA?",
questionTypeId: 3,
options: [
{
id: 18,
name: "Secured and Progressive App",
isAnswer: false,
isSelected: false
},
{
id: 19,
name: "Single Page Application",
isAnswer: false,
isSelected: false
},
{
id: 20,
name: "SOLID Principles for Application",
isAnswer: true,
isSelected: false
},
{
id: 21,
name: "None of the above",
isAnswer: false,
isSelected: false
}
]
}
],
Currentquestion: []
};
i would like to change the isSelected value to true from the questions array of which index having questionTypeId:1 followed by the options array of index:0
Below is the reducer i tried to change the state immutably action.payload value from the ui is 1 and action.value's value from the ui is 0
case SELECT_ANS: {
const question = action.payload;
const index = action.value;
// const newstate = produce(state, draftsate => {
// draftsate.questions[question].options[index].isSelected = true;
// });
return {
...state,questions:[
{
...state.questions[question],options:[{
...state.questions[question].options[index],isSelected:true
}]
}
]
]
]
};
I try to put all the information as much as i can if anything missing or inappropriate i'm sorry about ,Any help with explanation would be really appriciated ,Thanks in Advance
At first I notices you split your action's data into action.payload and action.value, this is against the flux principles. You must put your data object in action.payload and get it like action.payload.questionTypeId and action.payload.index.
Well, you can change your store like
case SELECT_ANS: {
return {
...store,
questions: store.questions.map((question) => {
if (question.questionTypeId === action.payload.questionTypeId) {
return {
...question,
options: question.options.map((option, index) => {
if (index === action.payload.index) {
return {
...option,
isSelected: true,
};
}
return option;
}),
};
}
return question;
}),
};
};
If I didn’t answer your question well enough, you can get more information in redux docs or ask me personally.
Good luck learning!
Hi I have following model of a document in mongodb
Schema is
const ProductionsSchema=new Schema({
name: {type: String, required: true, unique: true},
isActive: {type: Boolean, default: true},
locations: [{
name: {type: String},
isActive : {type: Boolean, default: false}
}],
trackno: {type: String}
})
Productions:[{
_id: 125,
name: 'John Smith',
locations: [{ name: 'Boston', isActive: true}]
isActive: true,
trackno: 2123
},
{
_id: 126,
name: 'Moe Adam',
locations: [{ name: 'Chicago', isActive: true}]
isActive: true,
trackno: 5663
},
{
_id: 126,
name: 'Henry Noel',
locations: [{ name: 'Houston', isActive: false}]
isActive: true,
trackno: 4552
},
{
_id: 128,
name: 'Tim Johnson',
locations: [{ name: 'Denver', isActive: true}]
isActive: false,
trackno: 6672
}
]
I am trying to find list of with both isActive true
Productions.find({"isActive" : true , "locations.isActive": true}, (err, list)=>{
if(err){
callback(err);
}
callback(null, list)
})
I am trying to write query so both isActive are true. In above sample data only first two records should be in the answer. But I keep getting all the records even ones with 'false' I even tried $elemMatch on locations.isActive still didnt work.
Please let me know how I can fix this so that I only get result that contains only true values for both isActive.
As the original comment explained, the only query conditions you need are:
{ isActive: true, "locations.isActive": true }
This is a basic AND condition, and you don't need any special operators just to verify a condition is met on a single property anywhere in an array, which is all you are asking.
Since this works exactly as expected, I can only think to show you a full working listing to use as a basis to work out what you are doing differently thus causing you to not get the same result as what is expected.
const { Schema } = mongoose = require('mongoose');
const uri = 'mongodb://localhost:27017/productions';
const opts = { useNewUrlParser: true };
mongoose.set('useFindAndModify', false);
mongoose.set('useCreateIndex', true);
mongoose.set('debug', true);
const productionSchema = new Schema({
name: String,
isActive: { type: Boolean, default: true },
locations: [{
name: String,
isActive: { type: Boolean, default: false }
}],
trackno: Number
})
const Production = mongoose.model('Production', productionSchema);
const data =
[
{
name: 'John Smith',
locations: [{ name: 'Boston', isActive: true}],
isActive: true,
trackno: 2123
},
{
name: 'Moe Adam',
locations: [{ name: 'Chicago', isActive: true}],
isActive: true,
trackno: 5663
},
{
name: 'Henry Noel',
locations: [{ name: 'Houston', isActive: false}],
isActive: true,
trackno: 4552
},
{
name: 'Tim Johnson',
locations: [{ name: 'Denver', isActive: true}],
isActive: false,
trackno: 6672
}
];
const log = data => console.log(JSON.stringify(data, undefined, 2));
(async function() {
try {
const conn = await mongoose.connect(uri, opts);
// clean data
await Promise.all(
Object.entries(conn.models).map(([k, m]) => m.deleteMany())
);
// set up
await Production.insertMany(data);
// Query
let query = { isActive: true, "locations.isActive": true };
let results = await Production.find(query);
log(results);
} catch(e) {
console.error(e)
} finally {
mongoose.disconnect()
}
})()
Which outputs the two expected documents:
Mongoose: productions.deleteMany({}, {})
Mongoose: productions.insertMany([ { isActive: true, _id: 5c7f7e9367daed19d6773e9b, name: 'John Smith', locations: [ { isActive: true, _id: 5c7f7e9367daed19d6773e9c, name: 'Boston' } ], trackno: 2123, __v: 0 }, { isActive: true, _id: 5c7f7e9367daed19d6773e9d, name: 'Moe Adam', locations: [ { isActive: true, _id: 5c7f7e9367daed19d6773e9e, name: 'Chicago' } ], trackno: 5663, __v: 0 }, { isActive: true, _id: 5c7f7e9367daed19d6773e9f, name: 'Henry Noel', locations: [ { isActive: false, _id: 5c7f7e9367daed19d6773ea0, name: 'Houston' } ], trackno: 4552, __v: 0 }, { isActive: false, _id: 5c7f7e9367daed19d6773ea1, name: 'Tim Johnson', locations: [ { isActive: true, _id: 5c7f7e9367daed19d6773ea2, name: 'Denver' } ], trackno: 6672, __v: 0 } ], {})
Mongoose: productions.find({ isActive: true, 'locations.isActive': true }, { projection: {} })
[
{
"isActive": true,
"_id": "5c7f7e9367daed19d6773e9b",
"name": "John Smith",
"locations": [
{
"isActive": true,
"_id": "5c7f7e9367daed19d6773e9c",
"name": "Boston"
}
],
"trackno": 2123,
"__v": 0
},
{
"isActive": true,
"_id": "5c7f7e9367daed19d6773e9d",
"name": "Moe Adam",
"locations": [
{
"isActive": true,
"_id": "5c7f7e9367daed19d6773e9e",
"name": "Chicago"
}
],
"trackno": 5663,
"__v": 0
}
]
I am new to the react-redux.
Here I have an object which is like,
const initialState = {
Low: [
{
id: 0,
technologyId: 0,
technology: '',
type: '',
count: '',
allowded: 6,
level: 'EASY'
}
],
Medium: [
{
id: 0,
technologyId: 0,
technology: '',
type: '',
count: '',
allowded: 7,
level: 'MEDIUM'
}
],
High: [
{
id: 0,
technologyId: 0,
technology: '',
type: '',
count: '',
allowded: 7,
level: 'TOUGH'
}
]
}
Now, this value is set it in the reducer I am taking it as a props.
Now, onchnage here the object property gets change from one of these obj.
So, Here the way I am updating it is ,
onChange(event, tobeupdated, id, type, noc, data) {
let newData = { ...this.props.data };
if (newData) {
let data = newData[type].map((object, index) => {
if (object.id === id) {
object[tobeupdated] = event.target.value;
});
}
}
So,Here will I be updating the existing object ?
Or is there any another way ?
What I tried was,
{...object, [tobeupdated]: event.target.value}
it is giving the compile time errors .
How can I resolve this ?