javascript binary tree, check whether it is a mirror of itself - javascript

I learn javascript recently, I don't know why the code I wrote is wrong. Here is the quesion:Given a binary tree, check whether it is a mirror of itself.
var isSymmetric = function(root) {
if(root === null) return true;
function isSymmetric(leftNode, rightNode){
if(leftNode === null && rightNode === null) return true;
if(leftNode === null || rightNode === null) return false;
return (leftNode.val == rightNode.val) && isSymmetric(leftNode.left, rightNode.right) && isSymmetric(leftNode.right, rightNode.left);
}
isSymmetric(root.left, root.right);
};
when the input is 1, the result is "undefined". This algorithm is transformed from my Java code. Please kindly inform me where I get wrong.

var isSymmetric = function(root) {
if (root === null) return true;
function isSymmetric(leftNode, rightNode) {
if (leftNode === null && rightNode === null) return true;
if (leftNode === null || rightNode === null) return false;
return (leftNode.val == rightNode.val) && isSymmetric(leftNode.left, rightNode.right) && isSymmetric(leftNode.right, rightNode.left);
}
return isSymmetric(root.left, root.right);
};
you need to return the result of isSymmetric as shown above
personally, I wouldn't have the outer and inner functions have the same name, it looks confusing to my old eyes :p

Related

Javascript needs to prevent blanks from being entered

The following Javascript is attached to a field form (on change ) it is supposed to ensure that if the user clicks on a button then 'off site' will populate in activity_type. And if not then '95 Modifier' will appear. In addition this form sheet has a field I have checked 'required' yet what is happening is the user is able to enter blanks for activity type. Is there a way within this javascript to then not allow a blank to be entered?
if (getFormElement('activity_type_id').toUpperCase()=='EE641670-8BE3-49FD-8914-030740D9DE72'
&& getFormElement('actual_location').toUpperCase()!='5E74C25C-6363-46BE-B030-16216B364F5A')
{
setFormElement('is_off_site',true);
} else
{
setFormElement('is_off_site',false);
}
{
setFormElement('is_off_site',false);
}
For your requirement custom function might solve your issue. It might cover almost your all primary scenarios. I have tried my best to update an answer with the best possibilities.
Please review it.
function isEmpty(inputValue) {
if(typeof inputValue === 'string' && (inputValue === '0' || inputValue === 'false' || inputValue === '[]' || inputValue === '{}' || inputValue === '')){
return true;
}else if(Array.isArray(inputValue) === true){
return inputValue.length === 0 ? true : false;
}else if(Array.isArray(inputValue) === false && (typeof inputValue === 'object' && inputValue !== null) && typeof inputValue !== 'undefined' && typeof inputValue !== null){
return Object.keys(inputValue).length === 0 ? true : false;
}else if(typeof inputValue === 'undefined'){
return true;
}else if(inputValue === null){
return true;
}else if(typeof inputValue === 'number' && inputValue === 0){
return true;
}else if(inputValue === false){
return true;
}else if(inputValue.length > 0 && inputValue.trim().length === 0){
return true;
}
return false;
}
console.log("isEmpty(' '): ",isEmpty(' '));
console.log("isEmpty(''): ",isEmpty(''));
console.log("isEmpty([]): ",isEmpty([]));
console.log("isEmpty({}): ",isEmpty({}));
console.log("isEmpty(): ",isEmpty());
const nullValue = null;
console.log("isEmpty(null): ",isEmpty(nullValue));
console.log("isEmpty(0): ",isEmpty(0));
console.log("isEmpty(false): ",isEmpty(false));
console.log("isEmpty('0'): ",isEmpty('0'));
console.log("isEmpty('false'): ",isEmpty('false'));
console.log("isEmpty('[]'): ",isEmpty('[]'));
console.log("isEmpty('{}') ",isEmpty('{}'));
console.log("isEmpty(''): ",isEmpty(''));
console.log("isEmpty('0.0'): ",isEmpty(0.0));

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

How to fix isInteger for Internet Explorer [duplicate]

i have this error in internet explorer console ' Object doesn't support property or method 'isInteger' ' how can i resolve it ?
code:
function verificaNota(nota){
if (nota.length>0){
var arr = [];
if( nota.indexOf(".") != -1 ){
return ferificareArrayNote(nota.split('.'));
}else if( nota.indexOf(",") != -1 ){
ferificareArrayNote(nota.split(','));
}else if( nota.length<=2 && Number.isInteger(Number(nota)) && Number(nota)<=10 && Number(nota) > 0){
return true;
}else {
return false;
}
}
return true;
}
And yes, i pass it a number not char;
As stated by #Andreas, Number.isNumber is part of ES6 so not supported by IE11
You can add the following polyfill to you javasript
Number.isInteger = Number.isInteger || function(value) {
return typeof value === "number" &&
isFinite(value) &&
Math.floor(value) === value;
};
source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger

How to check null and undefined both values for the property?

I have two properties where i need to check null and undefined both for each, how can i use that in if else statements ?
main.js
var validateControlRating = function () {
if ( ($scope.controlProcessRatingDTO.controlPerformanceRatingKey === null ||
$scope.controlProcessRatingDTO.controlPerformanceRatingKey === undefined)
&&
($scope.controlProcessRatingDTO.controlDesignRatingKey === null ||
$scope.controlProcessRatingDTO.controlDesignRatingKey === undefined) ) {
$scope.caculatedRatingDiv = false;
} else {
$http.get('app/control/rest/calculateControlEffectiveness/' + $scope.controlProcessRatingDTO.controlDesignRatingKey + '/' + $scope.controlProcessRatingDTO.controlPerformanceRatingKey).success(function (data) {
$scope.calcaulatedRating = data;
}, function (error) {
$scope.statusClass ='status invalid userErrorInfo';
var errorMessage = error.data.errorMsg;
if (error.data.techErrorMsg) {
errorMessage = error.data.techErrorMsg;
}
$scope.statusInfo = errorMessage;
});
$scope.ratingValidationMsg = '';
$scope.ratingWinValidationClass = 'valid';
$scope.caculatedRatingDiv = true;
$scope.enableRatingSave = false;
}
};
It's a little tedious in javascript, you have to write each condition, and use parentheses etc
if ( ($scope.controlProcessRatingDTO.controlPerformanceRatingKey === null ||
$scope.controlProcessRatingDTO.controlPerformanceRatingKey === undefined)
&&
($scope.controlProcessRatingDTO.controlDesignRatingKey === null ||
$scope.controlProcessRatingDTO.controlDesignRatingKey === undefined) ) {...
or just
if ([null, undefined].indexOf( $scope.controlProcessRatingDTO.controlPerformanceRatingKey ) === -1
&&
[null, undefined].indexOf( $scope.controlProcessRatingDTO.controlDesignRatingKey ) === -1) {...
I think you need to to check this correclty, check for undefined then for null
and use && not || because your code will go to check null value for undefined variable and this surely will throw exception
code:
if( typeof myVar == 'undefined' ? false: myVar )
{ // go here defined and value not null
}
or
code:
if(typeof myVar != 'undefined' && myVar)
{ // go here defined and value not null
}
In your code check will go like
if ((typeof $scope.controlProcessRatingDTO.controlDesignRatingKey !== undefined||
typeof $scope.controlProcessRatingDTO.controlPerformanceRatingKey !== undefined) &&
($scope.controlProcessRatingDTO.controlDesignRatingKey !== null ||
$scope.controlProcessRatingDTO.controlPerformanceRatingKey !== null)) {
// do home work
}else { // do other home work }
You can use negate operator as well, but this would make work for "false" as well:
if (!$scope.controlProcessRatingDTO.controlPerformanceRatingKey && !$scope.controlProcessRatingDTO.controlDesignRatingKey) {
This is a bit shorter but if you want to treat False values separately, then use the Adeneo's answer above.
You could do this:
if ( some_variable == null ){
// some_variable is either null or undefined
}
taken from: How to check for an undefined or null variable in JavaScript?

Categories

Resources