How to check diffrence between two Objects and add missing values?
Example: https://jsfiddle.net/aca0hdv9/
var defaultOptions = {
monit : {
map:{
googleMap: false
},
vehiclesList: {
rightSide: false,
number: true,
driver: true,
note: true,
},
vehicleCloud: {
speed: true,
date: true,
alarms: true,
fuelsCloud: true
},
driverCloud: true
};
var userCacheOptions = {
monit : {
// Missing map options
vehiclesList: {
rightSide: false,
number: false,
driver: false
// Missing note option
},
vehicleCloud: {
speed: true,
date: true,
alarms: true,
fuelsCloud: true
},
// Missing driverCloud option
}
};
I don't want to assign default values, i just want add missing values. Any idea how to do this in the least complicated way?
You can use Object.keys to get all ennumerable keys. From there, you simply have to iterate over them.
var defaultOptions = {
monit: {
map: {
googleMap: false
},
vehiclesList: {
rightSide: false,
number: true,
driver: true,
note: true,
},
vehicleCloud: {
speed: true,
date: true,
alarms: true,
fuelsCloud: true
},
driverCloud: true
}
};
var userCacheOptions = {
monit: {
// Missing map options
vehiclesList: {
rightSide: false,
number: false,
driver: false
// Missing note option
},
vehicleCloud: {
speed: true,
date: true,
alarms: true,
fuelsCloud: true
}
// Missing driverCloud option
}
};
function fillBlanks(receiver, giver) {
var receiverkeys = Object.keys(receiver);
var giverkeys = Object.keys(giver);
for(var i = 0; i < giverkeys.length; i++) {
if(typeof receiver[giverkeys[i]] != typeof giver[giverkeys[i]]) {
receiver[giverkeys[i]] = giver[giverkeys[i]];
}
if(receiver[giverkeys[i]] != giver[giverkeys[i]]) {
receiver[giverkeys[i]] = giver[giverkeys[i]];
}
}
}
fillBlanks(userCacheOptions.monit, defaultOptions.monit);
console.log(userCacheOptions.monit);
You could iterate over the keys and check for objects and call the function recursive with the new objects to check. If a value is missing, then set it to the default value.
function setDefault(user, def) {
Object.keys(def).forEach(function (k) {
if (def[k] !== null && typeof def[k] === 'object') {
if (!(k in user)) {
user[k] = {};
}
setDefault(user[k], def[k]);
return;
}
if (!(k in user)) {
user[k] = def[k];
}
});
}
var defaultOptions = { monit: { map: { googleMap: false }, vehiclesList: { rightSide: false, number: true, driver: true, note: true, }, vehicleCloud: { speed: true, date: true, alarms: true, fuelsCloud: true }, driverCloud: true } },
userCacheOptions = { monit: { vehiclesList: { rightSide: false, number: false, driver: false }, vehicleCloud: { speed: true, date: true, alarms: true, fuelsCloud: true }, } };
setDefault(userCacheOptions, defaultOptions);
console.log(userCacheOptions);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I would do this job as follows; It recursively iterates and modifies the userCacheOptions object at place.
var defaultOptions = {
monit : {
map:{
googleMap: false
},
vehiclesList: {
rightSide: false,
number: true,
driver: true,
note: true,
},
vehicleCloud: {
speed: true,
date: true,
alarms: true,
fuelsCloud: true
},
driverCloud: true
}
};
var userCacheOptions = {
monit : {
// Missing map options
vehiclesList: {
rightSide: false,
number: false,
driver: false
// Missing note option
},
vehicleCloud: {
speed: true,
date: true,
alarms: true,
fuelsCloud: true
},
// Missing driverCloud option
}
};
function restoreMissing(def,obj){
Object.keys(def).map(k => (typeof def[k] === "object" &&
typeof obj[k] === "object") ? restoreMissing(def[k],obj[k])
: !obj[k] && (obj[k] = def[k]));
return obj;
}
console.log(restoreMissing(defaultOptions,userCacheOptions))
This is the pattern that you want to follow, you just add the appropriate actions for each check.
if(!(defaultOptions.equals(userCacheOptions))){
//check for userCacheOptions if the value is set
//if its not set then set it as you want
if(!(userCacheOptions.getGoogleMap().isSet())){
userCacheOptions.setGoogleMap("whatever you want to set");
}
//same each variable etc
}
Related
I have two arrays
const condition = [
{ iosSend: true },
{ androidSend: true }
]
const myArray = [
{
androidSend: false,
iosSend: true,
macosSend: false,
id: 1
},
{
androidSend: true,
iosSend: false,
macosSend: false,
id: 2
},
{
androidSend: true,
iosSend: true,
macosSend: false,
id: 3
},
{
androidSend: false,
iosSend: false,
macosSend: true,
id: 4
}
]
Where I want to filter myArray with the following conditions:
Return a array with objects that has at least one of the keys of object inside condition array Equals false.
I mean, in the example, the return should return an array
with objects with ids 1, 2 and 4
Which is the best way to do this?
The following is an example of filtering if you wanted all items that match any condition.
const condition = {
iosSend: false,
androidSend: false
};
const myArray = [
{
androidSend: false,
iosSend: true,
macosSend: false,
id: 1
},
{
androidSend: true,
iosSend: false,
macosSend: false,
id: 2
},
{
androidSend: true,
iosSend: true,
macosSend: false,
id: 3
},
{
androidSend: false,
iosSend: false,
macosSend: true,
id: 4
}
];
const conditions = Object.entries(condition);
const filteredArr = myArray.filter(o => {
for (const [key, val] of conditions) {
if (key in o && o[key] == val) return true;
}
return false;
});
console.log(filteredArr);
#EDIT:
I changed conditions to be either iosSend false or androidSend false after clarifying comment from author
I have a global variable var room = {} when i create a rooms it will go there and i will have the object like this
{
'4bea542f-147c-4763-ab1c-bb6c40b1392e': {
private: false,
users: {
btrJ7946MkjFSz_zAAAA: [Object],
'qe_1igD7Q-RbDWc1AAAC': [Object]
},
gameS: false,
nextUser: 'btrJ7946MkjFSz_zAAAA',
timer: null,
round: 0,
winner: false,
alreadyGuess: [],
timerStartedAt: 0,
settings: { gameStarted: false, time: null }
},
'e6ea6785-e522-4b8c-aeb8-b2551e89c895': {
private: false,
users: {
'n5BODsuqAWb5Y-WAAAAD': [Object],
paf4cWgX08Qi_8m5AAAE: [Object]
},
gameS: false,
nextUser: 'n5BODsuqAWb5Y-WAAAAD',
timer: null,
round: 0,
winner: false,
alreadyGuess: [],
timerStartedAt: 0,
settings: { gameStarted: false, time: null }
}
}
How can i access these objects with different names like '4bea542f-147c-4763-ab1c-bb6c40b1392e' and maybe get the ones with values private = false
Depends what you want to accomplish, striclty speaking to your question Object.values() is probably the easiest, but it won't keep the key, which you might be interested in keeping.
to get the keys, use keys
var publicRoomsIds = Object.keys(rooms).filter(function (key) {
var room = rooms[key];
return (room.private === false);
});
to get the values (without keys) use values
var publicRooms = Object.values(rooms).filter(function (room) {
return (room.private === false);
});
var rooms = {
"4bea542f-147c-4763-ab1c-bb6c40b1392e": {
private: false,
},
"e6ea6785-e522-4b8c-aeb8-b2551e89c895": {
private: true,
},
"e6ea6785-3321-4b8c-aeb8-b2551e89c895": {
private: false,
},
"e6ea6785-7663-4b8c-aeb8-b2551e89c895": {
private: true,
},
};
var publicRoomsIds = Object.keys(rooms).filter(function (key) {
var room = rooms[key];
return (room.private === false);
});
var publicRooms = Object.values(rooms).filter(function (room) {
return (room.private === false);
});
console.log(publicRoomsIds);
console.log(publicRooms);
You can filter over Object.values.
const o = { '4bea542f-147c-4763-ab1c-bb6c40b1392e': { private: false, users: { btrJ7946MkjFSz_zAAAA: [Object], 'qe_1igD7Q-RbDWc1AAAC': [Object] }, gameS: false, nextUser: 'btrJ7946MkjFSz_zAAAA', timer: null, round: 0, winner: false, alreadyGuess: [], timerStartedAt: 0, settings: { gameStarted: false, time: null } }, 'e6ea6785-e522-4b8c-aeb8-b2551e89c895': { private: false, users: { 'n5BODsuqAWb5Y-WAAAAD': [Object], paf4cWgX08Qi_8m5AAAE: [Object] }, gameS: false, nextUser: 'n5BODsuqAWb5Y-WAAAAD', timer: null, round: 0, winner: false, alreadyGuess: [], timerStartedAt: 0, settings: { gameStarted: false, time: null } } };
const res = Object.values(o).filter(x => !x.private);
console.log(res);
.as-console-wrapper{top:0;max-height:100%!important}
If you also want the key, you could use Object.keys or Object.entries.
I have an array of objects.
const people = [
{
active: true,
hasMoney: false
},
{
active: false,
hasMoney: false
},
{
active: true,
hasMoney: true
}
]
I want to sort the data in this order: active: true -> hasMoney: true -> active: false -> hasMoney: false
Important: If the user is active === true and hasMoney === true, then this should be ordered after active === true and hasMoney === false
I tried the following but it didn't work. Anyone have any ideas?
people
.sort((x, y) =>
x.hasMoney
? Number(x) - Number(y)
: Number(isPersonActive(y)) - Number(isPersonActive(x))
)
You could take the delta of the boolean values and sort by two properties with a special look to the sorting of same values.
const people = [{ active: false, hasMoney: true }, { active: true, hasMoney: false }, { active: false, hasMoney: false }, { active: true, hasMoney: true }];
people.sort((a, b) =>
b.active - a.active ||
(a.hasMoney === b.active) - (a.active === b.hasMoney)
);
console.log(people);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can do the following,
const people = [
{
active: true,
hasMoney: true
},
{
active: false,
hasMoney: false
},
{
active: true,
hasMoney: false
}
]
people.sort((a, b) => {
if(a.active && b.active) {
return a.hasMoney - b.hasMoney;
} else if(a.active) {
return -1;
} else if(b.active) {
return 1;
} else {
return b.hasMoney - a.hasMoney;
}
})
console.log(people);
The following sort with a OR condition as per provided condition.
const people = [
{
active: true,
hasMoney: false
},
{
active: false,
hasMoney: false
},
{
active: false,
hasMoney: true
},
{
active: true,
hasMoney: false
}
];
const a = people.sort((a,b) => b.active-a.active || (b.hasMoney - a.hasMoney));
console.log(a);
const people = [
{
active: true,
hasMoney: true
},
{
active: false,
hasMoney: false
},
{
active: true,
hasMoney: false
},
{
active: false,
hasMoney: true
}
]
let peopleSorted = people.sort((a, b) => {
if (a.active == b.active) {
if (a.hasMoney < b.hasMoney) {
return 1;
} else if (a.hasMoney > b.hasMoney) {
return -1;
} else {
return 0;
}
} else if (a.active) {
return -1;
} else if (b.active) {
return 1;
} else {
return 0;
}
});
console.log(peopleSorted);
Try like this. when both are active (on campare), sort on hasMoney
const sort = (arr) => arr.sort((a, b) => {
if (a.active === b.active) {
return b.hasMoney - a.hasMoney;
}
return b.active - a.active;
})
const people = [
{
active: true,
hasMoney: false
},
{
active: false,
hasMoney: false
},
{
active: true,
hasMoney: true
}
]
const people2 = [
{ active: true, hasMoney: false },
{ active: false, hasMoney: false },
{ active: false, hasMoney: true },
{ active: true, hasMoney: true },
];
console.log(sort(people))
console.log(sort(people2))
i have the following state:
state = {
profile: {
name: { value: '', isRequired: true, hasError: false, order: 1 },
industry: { value: '', isRequired: false, hasError: false, order: 2 },
address: { value: '', isRequired: false, hasError: false, order: 3 },
crn: { value: '', isRequired: true, hasError: false, order: 4 },
website: { value: '', isRequired: false, hasError: false, order: 5 },
employeesNbr: { value: '', isRequired: true, hasError: false, order: 6 },
phoneNumber: { value: '', isRequired: true, hasError: false, order: 7 },
userRole: { value: '', isRequired: true, hasError: false, order: 8 },
personCheck: {
value: false,
isRequired: true,
hasError: false,
order: 9,
},
},
showModal: {
modal: { error: false },
},
};
And I have the following section of a submit handler
if (
!profile.name.hasError &&
!profile.crn.hasError &&
!profile.employeesNbr.hasError &&
!profile.phoneNumber.hasError &&
!profile.userRole.hasError &&
profile.personCheck.hasError
) {
showModal.modal.error = true;
}
What ways can I use to enhance the if statement?
Thank you
In the following way it would be optimized since as soon as one of the profile.* props has hasError to true would "returns" (due the or instead of and): the and (&&) needs to evaluate all the conditions where the or || it stops as soon as one is true.
You can also probably remove the if statement:
showModal.modal.error = profile.personCheck.hasError && !(
profile.name.hasError ||
profile.crn.hasError ||
profile.employeesNbr.hasError ||
profile.phoneNumber.hasError ||
profile.userRole.hasError)
Do you like it better that way?
if (
!(profile.name.hasError ||
profile.crn.hasError ||
profile.employeesNbr.hasError ||
profile.phoneNumber.hasError ||
profile.userRole.hasError) &&
profile.personCheck.hasError
) {
showModal.modal.error = true;
}
or if you prefer something more fancy:
if (
(Object.entries(state.profile)
.filter(prop => prop[1].hasError).length === 1) && // there is exactly one error
state.profile.personCheck.hasError // personCheck has error
)
It would be easy to simplify it into a loop if you were doing the same check for all properties in the profile. Doing a different check for personCheck makes it hard to reduce it like that.
You can use an array for all the properties that you want the same check on.
if (profile.personCheck.hasError &&
["name", "crn", "employeesNbr", "phoneNumber", "userRole"].every(prop => !profile[prop].hasError)) {
showModal.modal.error = true;
}
I am having a hard time trying to convert an object supplied in a specific format from API into a target format using javascript. Please note that in the target format, the false values are not present. This is intentional. Can someone please help by showing how I can do the this kind of conversion. Thank you
// Original format
const rules= [
{
dealer: {
view: true,
edit: false,
add: false
},
franchise: {
view: true,
edit: true,
add: true
},
branch: {
view: true,
edit: false,
add: false
}
}
]
// Target format
const rules = [
{
actions: ["view"],
subject: ["dealer"]
},
{
actions: ["view"],
subject: ["franchise"]
},
{
actions: ["edit"],
subject: ["franchise"]
},
{
actions: ["add"],
subject: ["franchise"]
},
{
actions: ["view"],
subject: ["branch"]
}
];
I implemented mapping function which take each item and map it according to the value if true
let rules = [
{
dealer: {
view: true,
edit: false,
add: false
},
franchise: {
view: true,
edit: true,
add: true
},
branch: {
view: true,
edit: false,
add: false
}
}
]
rules = rules.map(item => {
const keys = Object.keys(item);
let mappedItem = []
keys.forEach(key => {
for (const property in item[key]) {
if (item[key][property]) {
mappedItem.push({ subject: [key], actions: [property] })
}
}
})
return mappedItem;
});
let rules= [
{
dealer: {
view: true,
edit: false,
add: false
},
franchise: {
view: true,
edit: true,
add: true
},
branch: {
view: true,
edit: false,
add: false
}
}
];
const result = rules.map(obj => Object.keys(obj).map(k => ({
subject: [k],
actions: Object.keys(obj[k]).filter(action => obj[k][action])
})).reduce((acc, cur) => ([
...acc,
...cur.actions.map(a => ({subject: cur.subject, actions: [a]}))
]),[]))
console.log(result);