How to optimize multiple variable check - javascript

const {
service,
customer,
company,
parking,
aircraftType,
aircraft,
endPlan,
startPlan,
heatingPointsMasterCodes,
lavatoryType,
passengersCategory } = formValues;
useEffect(() => {
customer &&
company &&
(parking || service === ReferenceCodesOfServicesEnum.ProvisioningMinibus) &&
aircraftType &&
aircraft &&
endPlan &&
startPlan &&
(heatingPointsMasterCodes ||
lavatoryType ||
passengersCategory ||
formValues[DocumentItemNamesEnum.WaterSystemMaintenance] ||
service === ReferenceCodesOfServicesEnum.AircraftCooling)
? setDisabled(false)
: setDisabled(true);
}, [formValues]);
So my question is, how to optimize or reduce variable check for true value?
First i get variables with destructing from object, then check same variables for true value.
I think i can somehow optimize this, but dont know how

In general if you have a series of if checks you could consider turning it into a switch instead. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/switch
Since you're mostly checking to make sure things are defined, but also have some more nuanced requirements, it may be better break it up slightly:
// Properties required irrespective of environment properties in DocumentItemNamesEnum or ReferenceCodesOfServicesEnum
const requiredProperties = ["customer",
"company", "aircraftType",
"aircraft", "endPlan",
"startPlan"]
const requiredPropertiesDefined = requiredProperties.every(value => !!value)
useEffect(() => {
if (requiredPropertiesDefined &&
(formValues.parking || formValues.service === ReferenceCodesOfServicesEnum.ProvisioningMinibus) &&
&& (formValues.heatingPointsMasterCodes ||
formValues.lavatoryType ||
formValues.passengersCategory ||
formValues[DocumentItemNamesEnum.WaterSystemMaintenance] ||
service === ReferenceCodesOfServicesEnum.AircraftCooling) {
setDisabled(true)
} else {
setDisabled(false
}
}, [formValues])

If you want to check if all values of object are truthy then following code can be used.
Object.values(formValues).every(value => !!value)

Related

How to check if a multiple repeated logic conditions are true in JS

I'm trying to make a bot for the popular game Minecraft but I ran into an issue, my bot got stuck in NPCs (I was testing it in a server) and so I decided to make the code ignore the NPCs by seeing their name and then deciding if it should walk up to them or not. Then I met this issue:
var playerFilter = (entity) => entity.type === "player" && entity.username != "fuud" && entity.username != "snowboi" && entity.username != "fugdealer1" && entity.username != "parkourstart" && entity.username != "boatman" && entity.username != "timber + nails" && entity.username != "mrshade"
It's repeated and I'd like to see if there is any way to shorten it into a list or something like that. This variable is used many times in the code.
Use an array and the .includes() method.
var playerFilter = (entity) => entity.type === "player" && !["fuud", "snowboi", "fugdealer1", "parkourstart", "boatman", "timber + nails", "mrshade"].includes(entity.username)
console.log(playerFilter({type: "player", username: "somethingelse"}))
console.log(playerFilter({type: "player", username: "mrshade"}))

Based on array elements returning different output

i have caluclateAcess function which takes an array as input ,
the array will have max of three elements and min of one element
so the possible elements it can come is create, read and update
so its basically 2^3 which means 8 probabablities can come so
i am listing down all the probabablities and returning a value
i will list down the possible input and what output should i return. Array of empty wont be comming which means false, false, false
create => 'CreateAndRead'
read => 'Read'
update => 'UpdateAndRead'
create,read => 'CreateAndRead'
update, read => 'UpdateAndRead'
create, update => 'ALL'
create,read, update => 'ALL'
so i have written the below function is there any better way to achieve this
let READ = 'read';
let CREATE = 'create';
let UPDATE = 'update';
const caluclateAcess = (inputArray) => {
if (
(inputArray.indexOf(READ) > -1
&& inputArray.indexOf(UPDATE) > -1
&& inputArray.indexOf(CREATE) > -1)
||
(
inputArray.indexOf(UPDATE) > -1
&& inputArray.indexOf(CREATE) > -1
)
) {
return 'ALL';
}
if (
(inputArray.indexOf(CREATE) > -1
&& inputArray.indexOf(READ) > -1)
|| (inputArray.indexOf(CREATE) > -1
&& (inputArray.indexOf(READ) === -1 && inputArray.indexOf(UPDATE) === -1))
) {
return 'CreateAndRead';
}
if (
(inputArray.indexOf(UPDATE) > -1
&& inputArray.indexOf(READ) > -1)
|| (inputArray.indexOf(UPDATE) > -1
&& (inputArray.indexOf(READ) === -1 && inputArray.indexOf(CREATE) === -1))
) {
return 'UpdateAndRead';
}
if (inputArray.indexOf(READ) > -1) {
return 'Read';
}
};
Any help appreciated
You can start off by removing the repeat inputArray.indexOf() calls - it makes everything harder to read. It's simpler to check these once only:
const hasCreate = inputArray.indexOf(CREATE) > -1;
const hasUpdate = inputArray.indexOf(UPDATE) > -1;
const hasRead = inputArray.indexOf(READ) > -1;
Second, the rules you set up show that you have three access properties - read, update, and create, each one may imply another. Looking at those, it becomes clear that you have the following relationships:
read => read
update => update, read
create => create, read
Thus, update and create are actually compound. This means that the initial check can be modified to account for these:
const hasCreate = inputArray.indexOf(CREATE) > -1;
const hasUpdate = inputArray.indexOf(UPDATE) > -1;
const hasRead = hasCreate || hasUpdate || inputArray.indexOf(READ) > -1;
This avoids having the checks for if somebody has read or update.
As an extra note, you can just use Array#includes instead of checking the index.
With that said, the read right is pretty much inconsequential. It matters if it's the only one available, in all other cases it's pretty much ignored or assumed to be present. Still, it's useful to model the implied rules - perhaps this can change in the future.
Finally, the logic is too complex. There are only four possible final states and as mentioned above, read is not even used for most of them. Here is the updated code that does all the checks. I've added another state called "None" for the case when there are no permissions at all. Even if it's not possible for this to happen, I find it easier to just have it and it be unused than omit it:
const caluclateAcess = (inputArray) => {
const hasCreate = inputArray.includes('create');
const hasUpdate = inputArray.includes('update');
const hasRead = hasCreate || hasUpdate || inputArray.includes('read');
if (hasCreate === true && hasUpdate === true) return "ALL";
if (hasCreate) return "CreateAndRead";
if (hasUpdate) return "UpdateAndRead";
if (hasRead) return "Read";
return "None";
};
console.log("create =>", caluclateAcess(["create"]) );
console.log("read =>", caluclateAcess(["read"]) );
console.log("update =>", caluclateAcess(["update"]) );
console.log("create, read =>", caluclateAcess(["create", "read"]) );
console.log("update, read=>", caluclateAcess(["update", "read"]) );
console.log("create, update =>", caluclateAcess(["create", "update"]) );
console.log("create, read, update =>", caluclateAcess(["create", "read", "update"]));
console.log("<nothing> =>", caluclateAcess([]) );
The READ, CREATE, and UPDATE variables are not needed, since they are only used once, so I inlined them to shorten the code even more.
However, if there really is no possibility for an empty array of access properties, then that implies that the read access is completely inconsequential. It's impossible to not have it. So, checking for it can be entirely skipped and the default return value of the function can be changed from "None" to "Read". However, my personal preference is to keep the check - it doesn't hurt any of the functionality and the implementation produces no deviation from the specs. If the specs change in the future, or there is some sort of bug, it's probably better to not automatically grant read access.

Use Ternary operator instead of if..else in javascript

Instead of if...else statement how to do using ternary operation or any alternative way to simplify code in javascript
if(req.query.pr=="trans"){
util.transUrl(req.originalUrl).then(param => {
res.redirect(param);
})
}
else if(req.query.pr=="inst"){
util.instaUrl(req.originalUrl).then(param => {
res.redirect(param);
})
}
else{
res.status(400).send("Contact the editor of the originating page.")
}
There are multiple ways to write a conditional statement in JS. However, if there are multiple statements I would say you should stick to if else if else. But if you want to see other approaches, here they are:
Using Ternary operator ? :
const {pr} = req.query
pr === 'trans'
? util.transUrl(req.originalUrl).then(param =>
res.redirect(param)
)
: pr === 'inst'
? util.instaUrl(req.originalUrl).then(param =>
res.redirect(param)
)
: res.status(400).send('Contact the editor of the originating page.')
Using Gate logic && ||
const {pr} = req.query
(pr === 'trans' &&
util.transUrl(req.originalUrl).then(param =>
res.redirect(param))
) ||
(pr=== 'inst' &&
util.instaUrl(req.originalUrl).then(param =>
res.redirect(param))
) ||
res.status(400).send('Contact the editor of the originating page.')
Now, Looking at your code, here if and else if statements are similar. So you can avoid else if using ternary operator like this:
const {pr} = req.query
if(pr === 'trans' || pr === 'inst'){
util[pr === 'trans' ? 'transUrl' : 'instaUrl'](req.originalUrl)
.then(param => res.redirect(param))
}
else{
res.status(400).send('Contact the editor of the originating page.')
}
Just one FYI: Please consider using === instead of == whenever you are comparing strings and there is no need of coercion.

shorter code instead of using IF for all the combinations

I try to add all the combinations using IF but it's a lot to write. If I get the user sign and another user sign for example Aries with Aries I send an output ("high much") but I have 12*12=144 combinations!
Is there any option to do it shorter?
<script>
function hatama() {
signYours= $("input[name='sign1']").val()
signFriend=$("input[name='sign2']").val()
//Aries
if (signYours=="Aries" && signFriend=="Gemini")|| (signYours=="Aries" && signFriend=="Leo")|| (signYours=="Aries" && signFriend=="Saggitarious")|| (signYours=="Aries" && signFriend=="Libra")||(signYours=="Aries" && signFriend=="Aquarius")
$("#output").val("High");
if (signYours=="Aries" && signFriend=="Aries")||(signYours=="Aries" && signFriend=="Virgo") || (signYours=="Aries" && signFriend=="Capricon") ||
$("#output").val("Medium");
if (signYours=="Aries" && signFriend=="Pisces") || (signYours=="Aries" && signFriend=="Cancer")|| (signYours=="Aries" && signFriend=="Scorpio")
$("#output").val("Low");
//Taurus
if (signYours=="Taurus" && signFriend=="Virgo")|| (signYours=="Taurus" && signFriend=="Capricon")||(signYours=="Taurus" && signFriend=="Taurus")||(signYours=="Taurus" && signFriend=="Cancer")||(signYours=="Taurus" && signFriend=="Scorpio")||(signYours=="Taurus" && signFriend=="Pisces")
$("#output").val("High");
if (signYours=="Taurus" && signFriend=="Aquarius")||(signYours=="Taurus" && signFriend=="Taurus")
$("#output").val("Medium");
if (signYours=="Taurus" && signFriend=="Gemini")|| (signYours=="Taurus" && signFriend=="Leo")||(signYours=="Taurus" && signFriend=="Saggitarious")
$("#output").val("Low");
</script>
One option is to use an object whose properties are your signs, whose values are objects with High, Medium and Low properties, whose values are the associated signs:
// Object indexed by your own sign:
const signs = {
Aries: {
High: ['Gemini', 'Leo', 'Saggitarious', 'Libra', 'Aquarius'],
Medium: ['Aries', 'Virgo', 'Capricon'],
Low: ['Pisces', 'Cancer', 'Scorpio']
}
// ...
};
const getAssoc = (signYours, signFriend) => {
const yourObj = signs[signYours];
if (!yourObj) {
return "Your sign is invalid";
}
const foundEntry = Object.entries(yourObj)
.find(([_, arr]) => arr.includes(signFriend));
if (!foundEntry) {
return "Friend's sign is invalid";
}
return foundEntry[0];
};
console.log(getAssoc('Aries', 'Gemini'));
console.log(getAssoc('Aries', 'Scorpio'));
So, for your code:
function hatama() {
const signYours = $("input[name='sign1']").val();
const signFriend = $("input[name='sign2']").val();
$("#output").val(getAssoc(signYours, signFriend));
}
(make sure to always declare variables, else you'll implicitly create properties on the global object, which should be avoided)
If you need to make properties on signs for every possible sign, there may be an even more efficient way, if there is a pattern to the High/Medium/Low associations.
IMHO the problem here is to have a well structured data instead of a sequence of IF statements, checkout my solution by configuration:
const signs = [
{
userSign: "Aries",
associations: [
{
signs: ["Gemini","Leo", "Sagittarius", "Libra", "Acquarius"],
val: "High",
},
// further match
]
},
// furter signs
]
getMatchValue = (user1, user2) => {
let result;
const user1Sign = signs.find(
(sign) => sign.userSign === user1
);
user1Sign.associations.forEach(
(association) => {
if(association.signs.includes(user2)){
result = association.val;
}
}
)
return result;
}
console.log(getMatchValue("Aries", "Gemini"));

Multiple filters using lodash in React

I have a function that is filtering a large set of objects based on inputs that looks like so:
filterLocations(filters) {
let filteredLocations = _.filter(
this.state.locations,
location =>
location.beds >= filters.min &&
location.beds <= filters.max &&
location.baths >= filters.bathrooms &&
_.indexOf(filters.buildingTypes, location.buildingType.name) !== -1
);
this.setState({ filteredLocations: filteredLocations });
}
and in another component this is where the filters are set:
let filters = {
min: this.state.min || 0,
max: this.state.max || 99,
bathrooms: this.state.bathrooms || 0,
buildingTypes: this.state.selectedTypes || []
};
The first three work fine because the 'default values' are set regardless, so it makes filtering easy. But I am having trouble with figuring out the last part. If I select a buildingType it's fine and the filtering works as expected, but obviously if I leave it blank, the _.index(...) part tries to sort on nothing, so the resulting array is empty. I was wondering what would be the best way to rework the _.indexOf(...) part so I dont have to do something like:
buildingTypes: this.state.selectedTypes || ['list all options here']
Could you use a ternary to conditionally include the indexOf, and default to true without any buildingTypes so the expression will evaluate to true if all of the others are also true?
filterLocations(filters) {
const filteredLocations = _.filter(
this.state.locations,
location =>
location.beds >= filters.min &&
location.beds <= filters.max &&
location.baths >= filters.bathrooms &&
(filters.buildingTypes.length > 0
? _.indexOf(filters.buildingTypes, location.buildingType.name) !== -1
: true)
);
this.setState({ filteredLocations });
}

Categories

Resources