Shorthand JS Condition - javascript

I need a bit of assistance with this shorthand condition. My attempt at it so far is becoming a bit of a challenge and cant seem to make it more readable. I believe it was short circuited from minifying.
if (a === !0 || perSearch.rates.fy2) {
e();
} else if ( perSearch.rates.fy1.multiple || perSearch.rates.fy2.multiple ){
calculateRates();
} else {
perSearch.rates.fy1.multiple;
}
From this terse expression:
a === !0 || (perSearch.rates.fy2 ? perSearch.rates.fy1.multiple || perSearch.rates.fy2.multiple ? e() : calculateRates() : perSearch.rates.fy1.multiple ? e() : calculateRates())

Your expression corresponds to
if (a === !0) {
} else {
if (perSearch.rates.fy2) {
if (perSearch.rates.fy1.multiple || perSearch.rates.fy2.multiple) {
e();
} else {
calculateRates();
}
} else {
if (perSearch.rates.fy1.multiple) {
e();
} else {
calculateRates();
}
}
}
which can be simplified to
if (a !== true) {
if (perSearch.rates.fy1.multiple || (perSearch.rates.fy2 && perSearch.rates.fy2.multiple)) {
e();
} else {
calculateRates();
}
}

This should be it:
if (a !== false) {
if (perSearch.rates.fy2) {
if (!perSearch.rates.fy1.multiple) {
if (perSearch.rates.fy2.multiple) {
e()
}
else {
calculateRates()
}
}
}
else {
if (perSearch.rates.fy1.multiple) {
e()
}
else {
calculateRates()
}
}
}

Is this a return of some sort (return a || result), or a large conditional (a is true or this other code evaluates true)?. Either way I would tend to attack it in stages, block code, then abstract, repeat until the code looks manageable.
Block
Block out your conditionals to make it easier to read.
(
a === !0
|| (
perSearch.rates.fy2
? (perSearch.rates.fy1.multiple || (perSearch.rates.fy2.multiple ? e() : calculateRates()))
: (perSearch.rates.fy1.multiple ? e() : calculateRates())
)
)
Abstract
Abstract out some any big easy repetitions of logic.
const x = rates => ( (rates) ? e() : calculateRates() );
(
a === true || (perSearch.rates.fy2)
? ((perSearch.rates.fy1.multiple) || x(perSearch.rates.fy2.multiple))
: x(perSearch.rates.fy1.multiple)
)
Continue
Work into the code to separate out the conditionals.
const calc = rates => ((rates) ? e() : calculateRates());
const compare = rates => {
let fy1 = (rates.hasOwnProperty('fy1')) ? rates.fy1 : false;
let fy2 = (rates.hasOwnProperty('fy2')) ? rates.fy2 : false;
if (fy2) {
if (fy1.multiple) {
return fy1.multiple;
}
return calc(fy2.multiple);
} else {
return calc(fy1.multiple);
}
}
a === true || compare(perSearch.rates);
Edit (more continue!)
Looking at this again I think it would benefit from some early returns.
Look at conditional for simplification.
If fy2 and if fy1.multiple {return fy1.multiple}
If not fy2 {return fy1.multiple}
If fy2 and not fy1.multiple {return fy2.multiple}
const calc = rates => ((rates) ? e() : calculateRates());
const compare = rates => {
let fy1 = (rates.hasOwnProperty('fy1')) ? rates.fy1 : false;
let fy2 = (rates.hasOwnProperty('fy2')) ? rates.fy2 : false;
// consolidate conditions leading to same place.
if (!fy2 || (fy2 && fy1 && fy1.multiple)) {
return calc(fy1.multiple);
}
return calc(fy2.multiple);
}
a === true || compare(perSearch.rates);

Related

can we validate multiple functions inside if condition with AND operator using java script is there any other way to check multiple functions true?

I have added these functions and need return something based which function is returning true but it is not working.
//this is function1/
function A() {
return true;
}
function B() {
return true;
}
function C() {
if ({
{
var -customJS - page_type_lookup
}
} === 'product') {
var config = document.querySelector('#product-content > div.product-variations.clearfix > div.attribute.variant-dropdown > div.attribute-values-section > div.label.va-navSectionalOrientation').innerText;
if (config.includes('Sectional Orientation')) {
return true;
} else {
return false;
}
}
}
if (A() === true && B() === true && C() === true) {
return 'A+ Content, RTA Product, Sectional Configurator';
} else if (A() === true && B() === true) {
return 'A+ Content, RTA Product';
} else if (B() === true && C() === true) {
return 'RTA Product, Sectional Configurator';
} else if (C() === true && A() === true) {
return 'Sectional Configurator, A+ Content';
} else if (A() === true) {
return 'A+ Content';
} else if (B() === true) {
return 'RTA Product';
} else {
return 'Sectional Configurator';
}
}
If you have more than one function and a data set which reflects the wanted value of each flag, you could take an array for the functions retun values and another for the strings which are filterd and joined for the result.
const
flags = [a(), b(), c()],
result = ['A+ Content', 'RTA Product', 'Sectional Configurator']
.filter((_, i) => flags[i])
.join(', ');

Way to rewrite if..else conditions

I have lots of conditions and if I wrote it with if .. else it works fine but may be hard to read for others (especially if it will grow in future). Is there any better way how to rewrite it in more readable way?
My code:
func(el: IHeadlines): boolean => {
if (el.type === 'Cars' && el.label) { return true; }
if (el.type === 'Bikes' && el.storage) {
if (el.storage.filter(el => el.id === 1).length >= 1) { return true; }
if (el.storage.filter(el => el.id === 2).length > 1) { return true; }
} else return false;
}
interface IHeadlines {
type: string;
label: string;
storage: [{id: number; name: string}]
}
If you ask me, I create a function that counts the value and the code will be much more readable.
function count(arr, tar) {
cnt = 0;
for(let val of arr) {
if(val === tar)
cnt += 1;
}
return cnt;
}
You can write your function this way, this is way more readable to me:
const func = (el) => {
if (el.type === 'Cars' && el.label)
return true;
if (el.type === 'Bikes' && el.storage)
if(count(el.storage,1) >= 1 || count(el.storage,2) > 1)
return true;
return false;
}
Or this way:
const func = (el) => {
if (el.type === 'Cars' && el.label)
return true;
if ((el.type === 'Bikes' && el.storage) &&
(count(el.storage,1) >= 1 || count(el.storage,2) > 1))
return true;
return false;
For this is much more readable, however you can change the count function to any other way you like, and I would prefer using this code even if it is longer but it is much more readable.
Have you tried using switch-case?
for example:
function(el)=>{
switch(el.type):
case 'Cars':
return true;
break;
case 'Bikes':
return true;
break;
default:
return false;
}
After this, you can perhaps put if-else before 'return' in each case.
hello, i do some optimize. I wish this can help you.
const oldFunc = (el) => {
if (el.type === 'News' && el.label) {
return true;
}
if (el.type === 'Research' && el.storage) {
if (el.storage.filter(el => el.id === 1).length >= 1) {
return true;
}
if (el.storage.filter(el => el.id === 2).length > 1) {
return true;
}
} else return false;
}
// do some optimize
const newFunc = (el) => {
let flag = false;// default return false
flag = ((el.type === 'News' && el.label) ||
((el.type === 'Research' && el.hasOwnProperty('storage')) ? el.storage.some(o=>[1,2].includes(o.id)): false)) && true;
return flag;
}
// test code
const testData = {
type: 'News',
label: 'test'
};
console.log(oldFunc(testData));
console.log(newFunc(testData));
const testData2 = {
type: 'Research',
storage: [
{
id: 1,
name: "John"
}
]
};
console.log(oldFunc(testData2));
console.log(newFunc(testData2));
// test result
// true
// true
// true
// true
Two ways come to my mind, but none of them will make your code very clear because conditions are dirty stuff.
If you return boolean, you don't need if..else blocks. Just return the conditions.
func(el) => {
return (el.type === 'Cars' && el.label) ||
(el.type === 'Bikes' &&
(el.storage?.filter(el => el.id == 1).length >= 1 ||
el.storage?.filter(el => el.id == 2).length > 1)
)
}
You can extract the group of conditions to separate functions and call them in the main function.
const checkForCars = (el) => { return el.type === 'Cars' && el.label }
const checkForBikes = (el) => { return // your conditions}
const mainFunction (el) {
return checkForCars(el) || checkForBikes(el);
}
I generally try to be as descriptive as possible. Rename func to what the function does.
For readability, you could also create a function in el called, isCar(), isBike(), hasStorage() etc etc which would encapsulate that logic. I'm not sure if that makes sense based on what you provided. You are also inline hard coding ids. It would make it clearer if el contained some const / var or something in your app had them, which described the id. You could also rename el to something descriptive. You can remove some if by doing what Guerric P said.
Even the filter functions could be moved if they were going to be reused..
const shedFilter = (el) => ...(function code here)
Then provide some comments if anything is not clear.
const STORAGE_SHED = 1;
const SOTRAGE_GARAGE = 2;
aGoodName(el) => {
if (el.isCar()) { return true; }
if (el.isBike()) {
if (el.storage.filter(el => el.id === STORAGE_SHED ).length >= 1) { return true; }
if (el.storage.filter(el => el.id === SOTRAGE_GARAGE).length > 1) { return true; }
}
else { return false };
}
Step 1: To have exactly same logic as you had - you can start with extracting the conditions/function and trying to avoid return true and return false statements. You can easily return condition itself.
const isNews = el.type === 'News' && el.label;
const isBikes = el.type === 'Bikes' && el.storage;
const storageItemsCount = (el, id) => el.storage.filter(el.id === id).length;
return isNews
|| (isBikes && (storageItemsCount(el, 1) >= 1 || storageItemsCount(el, 2) > 1)
Step 2: further I would remove "magic" id 1 and 2 values and explicitly specify what they are about, like
const BIKE1_ID = 1;
const BIKE2_ID = 2;
no we can generalise the counts check with specifying
const minBikeCounts = {
[BIKE1_ID]: 1,
[BIKE1_ID]: 2
}
const bikeCountsAreValid = el => {
return Object.entries(k)
.every(
([id, minCount]) => el.storage.filter(el => el.id === key).length >= minCount)
}
so the main flow simplified to
const isNews = el.type === 'News' && el.label;
const isBikes = el.type === 'Bikes' && el.storage;
return isNews || (isBikes && bikeCountsAreValid(el))
Step 3: We can see a pattern of "Check if type is supported with some extra check". We could extract the knowledge of supported types to separate structure. Now if we want to add new supported type we don't need to remember all if/else statements across the codebase, and just add new one here:
const supportedTypes = {
News: el => !!el.label,
Bikes: el => !!el.storage && bikeCountsAreValid(el)
}
no if statements at all in our main function:
const isSuppotedType =
(el: IHeadlines) => supportedTypes[el.type] && supportedTypes[el.type](el)
Good clean code practices suggest that you have small functions and have a self-describing code.
In your code, I would make each Boolean logic become a variable or a function.
Example 1
func(element: IHeadlines): boolean => {
const isCarWithLabel = element.type === 'Cars' && element.label;
if(isCarWithLabel){
return true;
}
const isBikeWithStorage = element.type === 'Bikes' && element.storage;
if(isBikeWithStorage){
// rest of your logic that I don't know...
}
return false;
}
Example 2
func(element: IHeadlines): boolean => {
return this.isCarWithLabel() || this.isBikeWithStorageAndSomethingElse();
}
I'll suggest you something like this:
func(el: IHeadlines): boolean {
return el.type === 'Cars' && !!el.label ||
el.type === 'Bikes' && (
!!el.storage?.find(el => el.id == 1) || el.storage?.filter(el => el.id == 2).length > 1
);
}

DRY - Typescript. How can I use DRY principles to avoid duplication of these 2 getters

I know that below two getters are duplicates and could be consolidated and written in a better way. Could any one please help me come up with a way to consolidate these:-
isEqual here is a lodash library to compare two objects.
state in here is an injected state which I am picking the objects from.
public get isUpperModified(): boolean {
if (!this.isUpperAvailable) {
return false;
}
if (
(this.orders.upperPreference.type === '1' &&
this.state.fetchedData.upperPreference.type === '1') ||
(this.orders.upperPreference.type === 'UPPER' &&
this.state.fetchedData.upperPreference.type === 'UPPER')
) {
return false;
}
if (!isEqual(this.orders.upperPreference, this.state.fetchedData.upperPreference)) {
return true;
}
return false;
}
public get isLowerModified(): boolean {
if (!this.isLowerAvailable) {
return false;
}
if (
(this.orders.lowerPreference.type === '1' &&
this.state.fetchedData.lowerPreference.type === '1') ||
(this.orders.lowerPreference.type === 'LOWER' &&
this.state.fetchedData.lowerPreference.type === 'LOWER')
) {
return false;
}
if (!isEqual(this.orders.lowerPreference, this.state.fetchedData.lowerPreference)) {
return true;
}
return false;
}
There are more than 1 way to achieve this.
You can create a new function isModified(type: string) and pass upper or lower as an argument.
Hope this helps
public get isUpperModified(): boolean {
return this.isModified('upper');
}
public get isLowerModified(): boolean {
return this.isModified('lower');
}
private isModified(type: 'lower' | 'upper'): boolean {
const available = type === 'lower' ? this.isLowerAvailable : this.isUpperAvailable;
const order = type === 'lower' ? this.orders.lowerPreference : this.orders.upperPreference;
const state = type === 'lower' ? this.state.fetchedData.lowerPreference : this.state.fetchedData.upperPreference;
if (!available) {
return false;
}
if (
(order.type === '1' &&
state.type === '1') ||
(order.type === type.toUpperCase() &&
state.type === type.toUpperCase())
) {
return false;
}
if (!isEqual(order, state)) {
return true;
}
return false;
}
I would do it something like this
public get isModified(type: 'lower' | 'upper'): boolean {
const isAvailable = type === "lower" ? this.isLowerAvailable : this.isUpperAvailable
const preference = type === "lower" ? "lowerPreference" : "upperPreference";
if (!isAvailable) {
return false;
}
if (
(this.orders[preference].type === '1' &&
this.state.fetchedData[preference].type === '1') ||
(this.orders[preference].type === 'LOWER' &&
this.state.fetchedData[preference].type === 'LOWER')
) {
return false;
}
if (!isEqual(this.orders[preference], this.state.fetchedData[preference])) {
return true;
}
return false;
}
Then while calling this method
use isModified("upper") instead of isUpperModified
and
use isModified("lower") instead of isLowerModified

Are these JS conditional statements functionally equivalent?

Regarding conditional if/else statements, are the following examples functionally equivalent?
function isEntering() {
if (this.stage === 'entering') {
return true;
} else {
return false;
}
}
function isEntering() {
if (this.stage === 'entering') {
return true;
} return false;
}
function isEntering() {
if (this.stage === 'entering') {
return true;
}
}
isEntering = (this.stage === 'entering') ? true : false;
If so, I'd use the most terse of the options. But only if the four are functionally equivalent.
If expr is a boolean expression, as it is here, then there is no need to write
if (expr) return true;
else return false;
or to write
if (expr) x = true;
else x = false;
or to ever write
expr ? true : false
because being a boolean expression, expr can be returned, or assigned, directly:
return expr;
x = expr;
The tersest alternative is one you didn't give:
function isEntering() { return this.stage === 'entering'; }
They are not all equivalent.
The first two are equivalent, but:
function isEntering() {
if (this.stage === 'entering') {
return true;
}
}
Would return undefined if this.stage !== 'entering'.
Also:
isEntering = (this.stage === 'entering') ? true : false;
Is not defining a function as the other examples.
As mentioned you can add:
isEntering = () => this.stage === 'entering';
If you don't need a function you can use:
isEntering = this.stage === 'entering'

Recursion Function to search

How would I go about creating a recursive function that can search through a list for a node where x = 10?
I do not have any javascript experience so I am not sure where to start so would appreciate and input
I have come across the following code and tried to adapt it but I am not sure if I am on the right track:
function search(_for, _in) {
var r;
for (var p in _in) {
if ( p === 10 ) {
return _in[p];
}
if ( typeof _in[p] === 'object' ) {
if ( (r = search(_for, _in[p])) !== null ) {
return r;
}
}
}
return null;
}
Thank you in advance
Try this
var finder = function(needle, haystack) {
if (haystack.length == 0)
return false
if (haystack[0] == needle)
return true
return finder(pin, haystack.slice(1))
}
Or
var finder = function(pin, haystack) {
return (haystack[0] == pin) || (haystack.length != 0) && finder(pin, haystack.slice(1))
}
Recursion FTW

Categories

Resources