Categories
Python

More Things We Can Do With Regexes and Python

Python is a convenient language that’s often used for scripting, data science, and web development.

In this article, we’ll look at newline matches, case insensitive matching, and the sub method.

Matching Newlines with the Dot Character

We can use the re.DOTALL constant to match newlines.

For instance, we can use it as in the following code:

import re  
regex = re.compile(r'.\*', re.DOTALL)  
matches = regex.search('Jane\\nJoe')

Then we get ‘Jane\nJoe’ as the value returned bymatches.group() .

Without re.DOTALL , as in the following example:

import re  
regex = re.compile(r'.\*')  
matches = regex.search('Jane\\nJoe')

we get ‘Jane’ as the value returned bymatches.group() .

Summary of Regex Symbols

The following is a summary of regex symbols:

  • ? — matches 0 or 1 of the preceding group
  • * — matches 0 or more of the preceding group
  • + — matches one or more of the preceding group
  • {n} — matches exactly n of the preceding group
  • {n,} — matches n or more of the preceding group
  • {,n} — matches 0 to n of the preceding group
  • {n,m} — matches n to m of the preceding group
  • {n,m}? or *? or +? performs a non-greedy match of the preceding group
  • ^foo — matches a string beginning with foo
  • foo$ — matches a string that ends with foo
  • . matches any character except for new kine
  • \d , \w , and \s matches a digit, word, or space character respectively
  • \D , \W , and \S match anything except a digit, word, or space character respectively
  • [abc] — matches any character between the brackets like a, , b , or c
  • [^abc] — matches any character but a , b or c

Case-Insensitive Matching

We can pass in re.I to do case insensitive matching.

For instance, we can write:

import re  
regex = re.compile(r'foo', re.I)  
matches = regex.findall('FOO foo fOo fOO Foo')

Then matches has the value [‘FOO’, ‘foo’, ‘fOo’, ‘fOO’, ‘Foo’] .

Substituting Strings with the sub() Method

We can use the sub method to replace all substring matches with the given string.

For instance, we can write:

import re  
regex = re.compile(r'\\d{3}-\\d{3}-\\d{4}')  
new\_string = regex.sub('SECRET', 'Jane\\'s number is 123-456-7890. Joe\\'s number is 555-555-1212')

Since sub replaces the substring matches passed in as the 2nd argument and a new string is returned, new_string has the value of:

"Jane's number is SECRET. Joe's number is SECRET"

Verbose Mode

We can use re.VERBOSE to ignore whitespaces and comments in a regex.

For instance, we can write:

import re  
regex = re.compile(r'\\d{3}-\\d{3}-\\d{4} # phone regex', re.VERBOSE)  
matches = regex.findall('Jane\\'s number is 123-456-7890. Joe\\'s number is 555-555-1212')

Then matches has the value [‘123–456–7890’, ‘555–555–1212’] since the whitespace and comment in our regex is ignored by passing in the re.VERBOSE option.

Combining re.IGNORECASE, re.DOTALL, and re.VERBOSE

We can combine re.IGNORECASE , re.DOTALL , and re.VERBOSE with a pipe (|) operator.

For instance, we can do a case-insensitive and ignore whitespace and comments by writing:

import re  
regex = re.compile(r'jane # jane',  re.IGNORECASE | re.VERBOSE)  
matches = regex.findall('Jane\\'s number is 123-456-7890. Joe\\'s number is 555-555-1212')

The matches has the values ['Jane'] since we passed in re.IGNORECASE and combined it with re.VERBOSE with the | symbol to do a case-insensitive search.

Conclusion

We can pass in different arguments to the re.compile method to adjust how regex searches are done.

re.IGNORECASE lets us do a case-insensitive search.

re.VERBOSE makes the Python interpreter ignore whitespace and comments in our regex.

re.DOTALL let us search for matches with newline characters.

The 3 constants above can be combined with the | operator.

The sub method makes a copy of the string, then replace all the matches with what we passed in, then returns the string with the replacements.

Categories
Python

Intro to Python Boolean and Conditional Statements

Python is a convenient language that’s often used for scripting, data science, and web development.

In this article, we’ll look at how to use booleans and conditional statements in our Python programs.

Boolean Values

Boolean values take the value True or False . They always start with uppercase.

They can be used in expressions like anything else. For example, we can write:

foo = True

Comparison Operators

Comparison operators are used for comparison 2 values ane evaluate operands to a single boolean value.

The following comparison operators are included with Python:

  • == — equal to
  • != — not equal to
  • < — less than
  • > — greater than
  • <= — less than or equal to
  • >= — greater than or equal to

For example, we can write the following:

1 == 1

returns True .

1 != 2

returns False .

'hello' == 'Hello'

also returns False .

== is the equal to comparison operator, while the = is the assignment operator that assigns the right operand to the variable on the left.

Boolean Operators

The and operator takes 2 boolean values and then return one boolean value given the 2 operands.

It returnsTrue if both operands are True . Otherwise, it returns False .

The or operator takes 2 boolean values and returns one boolean value given the 2 operands.

It returns True if one or both operands are True . Otherwise, it returns False .

The not operator is a unary operator, which means it takes one operand.

It returns the negated value of the operand. This means that not True returns False and not False returns True .

Mixing Boolean and Comparison Operators

We can mix booleans and comparison operators since comparison operators return booleans.

For example, we can write:

(1 < 2) and (4 < 5)

which returns True .

Or:

(1 == 2) and (4 == 5)

which returns False .

Flow Control

We can combine conditions and blocks of code to create a program that has flow control.

The conditions can be used with the if or a combination of if , elif , or a combination of if , elife , and else together.

Blocks are indented. They begin when indentation increases and they can have blocks nested in it.

Blocks end when the indentation decreases to zero or to the containing block’s indentation.

For example, we can write the following if block;

print('Enter your name')  
name=input()  
if name == 'Mary':  
  print('Hello Mary')

The code above asks for the name and displays ‘Hello Mary’ if the name entered is 'Mary' .

We can add a nested if block as follows:

print('Enter your name')  
name=input()  
print('Enter your age')  
age=input()  
if name == 'Mary':  
  print('Hello Mary')  
  if int(age) < 18:  
    print('You are a girl')  
  else:  
    print('You are a woman')

In the code above, we have a nested if block that nest the age check in the name check.

We have the else block which runs if the int(age) < 18 returns False .

If we have more than 2 cases, we can use the elif keyword for checking and running code if alternative cases are True .

For example, we can use it as follows:

print('Enter your name')  
name=input()  
if name == 'Mary':  
  print('Hello Mary')  
elif name == 'Alex':  
  print('Hello Alex')  
elif name == 'Jane':  
  print('Hello Jane')  
else:  
  print('I do not know you')

Now if we enter Mary , Alex or Jane , we’ll see the Hello sentences displayed. Otherwise, we see I do not know you displayed.

Note that we always have a colon at the end of a if , elif and else lines.

The blocks are also indented. This is mandatory in Python to denote blocks.

Conclusion

Booleans are variables that can take the value True or False .

Comparison operators can be used to build expressions from other values. We can compare numbers and check if strings are equal.

They return boolean values, so they can be combined with the name operators to return boolean values.

and and or operators are used to combining expressions with comparison operators.

We can then use them in if statements to run code conditionally. For alternative cases, we can add them to elif and else keywords to denote them. They have to be used with if blocks.

Categories
JavaScript Vue

Introduction to Vue.js Routing

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In order to create a single-page app with Vue.js, we have to map URLs to components so that when users go to a URL, it’ll show the corresponding component.

In this article, we’ll look at how to create some simple routes with the Vue Router.

Getting Started

We can use by Vue Router by adding a script tag with the URL for the Vue Router library.

We can make a simple app as follows:

src/index.js :

const Foo = { template: "<div>foo</div>" };  
const Bar = { template: "<div>bar</div>" };

const routes = [  
  { path: "/foo", component: Foo },  
  { path: "/bar", component: Bar }  
];

const router = new VueRouter({  
  routes  
});

new Vue({  
  el: "#app",  
  router  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://unpkg.com/vue/dist/vue.js"></script>  
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      <div>  
        <router-link to="/foo">Foo</router-link>  
        <router-link to="/bar">Bar</router-link>  
      </div>  
      <router-view></router-view>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

In the code above, we defined 2 components Foo and Bar in src/index.js .

Then we mapped them to routes with:

const routes = [  
  { path: "/foo", component: Foo },  
  { path: "/bar", component: Bar }  
];

const router = new VueRouter({  
  routes  
});

Then we created a new Vue instance with:

new Vue({  
  el: "#app",  
  router  
});

In the template, we have router-links to map the routes to a tags with the URLs to correspond to the routes we define:

<router-link to="/foo">Foo</router-link>  
<router-link to="/bar">Bar</router-link>

Then we have router-view to show the components that are mapped to routes:

<router-view></router-view>

In the end, we should get:

Foo Link Bar Linkfoo

when we click on Foo Link .

and:

Foo Link Bar Linkbar

when we click on Bar Link .

Once we injected the router, we also get access to this.$router .

We can use it to navigate between routes. For example, we can write the following:

src/index.js :

const Foo = { template: "<div>foo</div>" };  
const Bar = { template: "<div>bar</div>" };

const routes = [  
  { path: "/foo", component: Foo },  
  { path: "/bar", component: Bar }  
];

const router = new VueRouter({  
  routes  
});

new Vue({  
  el: "#app",  
  router,  
  methods: {  
    goBack() {  
      window.history.length > 1 ? this.$router.go(-1) : this.$router.push("/");  
    }  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://unpkg.com/vue/dist/vue.js"></script>  
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      <div>  
        <router-link to="/foo">Foo Link</router-link>  
        <router-link to="/bar">Bar Link</router-link>  
        <a href="#" @click="goBack">Go Back</a>  
      </div>  
      <router-view></router-view>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

Then when we click the Foo Link and Bar Link links a few times then click Go Back , we’ll see it’ll go back to the previous routes that we navigated to.

Route Parameters

We can get route parameters with the this.$route.params object.

For example, we can write an app that shows the URL parameter that’s passed in as follows:

src/index.js :

const User = {  
  computed: {  
    username() {  
      return this.$route.params.username;  
    }  
  },  
  template: `<div>{{username}}</div>`  
};

const routes = [{ path: "/user/:username", component: User }];

const router = new VueRouter({  
  routes  
});

new Vue({  
  el: "#app",  
  router  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://unpkg.com/vue/dist/vue.js"></script>  
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      <div>  
        <router-link to="/user/foo">Foo</router-link>  
        <router-link to="/user/bar">Bar</router-link>  
      </div>  
      <router-view></router-view>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

The :username in “/user/:username” is the parameter, so we can get what passed in after /user/ by using this.$route.params.username .

We added a computed property username which returns this.$route.params.username so we can use:

`<div>{{username}}</div>`

to show the username URL parameter.

Conclusion

We can map URLs to components by using Vue Router.

Once we included it, we can define routes which map URLs to components. They can also take parameters, which can be retrieved with the this.$route object that’s made available by injecting the Vue router into our app.

To display links that link to Vue Router routes, we use router-link , and to display the components mapped to routes, we use router-view .

Categories
JavaScript Vue

Changing Scroll Behavior with Vue Router

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

Vue Router is a URL router that maps URLs to components.

In this article, we’ll look at how to change the scroll behavior of Vue Router routes.

Changing Scroll Behavior

Sometimes we may want to scroll to top when navigating to a new route or preserve the scrolling position of history entities like a real page reload.

Vue Router lets us adjust the scrolling behavior the way we like when route loads.

This only works if the browser supports history.pushState .

We can adjust scrolling behavior by providing a scrollBehavior function.

It has a to and from route objects as the first 2 parameters. The third argument is savePosition , is only available if this is a popstate navigation triggered by the browser’s back or forward buttons.

The function can return a scroll position object in the form of:

{ x: number, y: number }

or:

{ selector: string, offset? : { x: number, y: number }}

offset is supported since Vue Router 2.6.0

For example, we can add scrollBehavior to our routes as follows:

src/index.js:

const Foo = {  
  template: `  
    <div>  
      <div v-for='n in 100'>{{n}} foo</div>  
    </div>  
  `  
};  
const Bar = {  
  template: `  
  <div>  
    <div v-for='n in 100'>{{n}} bar</div>  
  </div>  
  `  
};

const routes = [  
  {  
    path: "/foo",  
    component: Foo  
  },  
  {  
    path: "/bar",  
    component: Bar  
  }  
];

const router = new VueRouter({  
  routes,  
  scrollBehavior(to, from, savedPosition) {  
    return { x: 0, y: 0 };  
  }  
});new Vue({  
  el: "#app",  
  router  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://unpkg.com/vue/dist/vue.js"></script>  
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      <router-view></router-view>  
      <router-link to="foo">Foo</router-link>  
      <router-link to="bar">Bar</router-link>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

In the code above, we have:

scrollBehavior(to, from, savedPosition) {  
  return { x: 0, y: 0 };  
}

to scroll the next page back to the top when we navigate. Therefore, when we click on the links at the bottom of the page, we’ll go back to the top.

If we return something falsy or an empty object, no scrolling will happen.

If we change scrollBehavior to:

scrollBehavior(to, from, savedPosition) {  
  if (savedPosition) {  
    return savedPosition;  
  } else {  
    return { x: 0, y: 0 };  
  }  
}

Then we keep the scroll position of the page when we navigate back and forth with the forward and back buttons.

We can create the scroll to anchor behavior by setting the ID on our elements and then changing scrollBehavior as follows:

src/index.js :

const Foo = {  
  template: `  
    <div>  
      <div v-for='n in 100' :id='n'>{{n}} foo</div>  
    </div>  
  `  
};

const routes = [  
  {  
    path: "/foo",  
    component: Foo  
  }  
];

const router = new VueRouter({  
  routes,  
  scrollBehavior(to, from, savedPosition) {  
    if (to.hash) {  
      return {  
        selector: to.hash  
      };  
    }  
  }  
});

new Vue({  
  el: "#app",  
  router  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://unpkg.com/vue/dist/vue.js"></script>  
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      <router-view></router-view>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

Then when we go to /#/foo#100 we scroll to the bottom, then when we go to /#/foo#20 , we see 20 foo at the top of the screen.

Async Scrolling

We can also to async scrolling with scrollBehavior since Vue Router 2.8.0 by returning a promise that resolves to the same objects as synchronous scrolling.

For example, we can change the example above to:

src/index.js :

const Foo = {  
  template: `  
    <div>  
      <div v-for='n in 100' :id='n'>{{n}} foo</div>  
    </div>  
  `  
};

const routes = [  
  {  
    path: "/foo",  
    component: Foo  
  }  
];

const router = new VueRouter({  
  routes,  
  scrollBehavior(to, from, savedPosition) {  
    if (to.hash) {  
      return new Promise((resolve, reject) => {  
        setTimeout(() => {  
          resolve({  
            selector: to.hash  
          });  
        }, 1000);  
      });  
    }  
  }  
});

new Vue({  
  el: "#app",  
  router  
});

Then when we go to /#/foo#100 in our browser, we scroll to the bottom of the page after a second.

Conclusion

Scrolling behavior during route navigation can be changed by adding a scrollBehavior function to our router object. It takes the to and from parameters which are route objects, and a 3rd savedPosition parameter with the saved scroll position of the navigated route.

Scrolling behavior can be synchronous or asynchronous since Vue Router 2.8.0.

We can scroll to an element with the CSS selector or position.

Categories
Vue

Dynamic Route Matching with Vue Router

Vue.js is an easy to use web app framework that we can use to develop interactive front end apps.

In this article, we’ll look at how to match routes dynamically with Vue Router.

Route Parameters

We can get route parameters with the this.$route.params object.

For example, we can write an app that shows the URL parameter that’s passed in as follows:

src/index.js :

const User = {
  computed: {
    username() {
      return this.$route.params.username;
    }
  },
  template: `<div>{{username}}</div>`
};

const routes = [{ path: "/user/:username", component: User }];

const router = new VueRouter({
  routes
});

new Vue({
  el: "#app",
  router
});

index.html :

<!DOCTYPE html>
<html>
  <head>
    <title>App</title>
    <meta charset="UTF-8" />
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
  </head>
  <body>
    <div id="app">
      <div>
        <router-link to="/user/foo">Foo</router-link>
        <router-link to="/user/bar">Bar</router-link>
      </div>
      <router-view></router-view>
    </div>
    <script src="src/index.js"></script>
  </body>
</html>

The :username in “/user/:username” is the parameter, so we can get what passed in after /user/ by using this.$route.params.username .

We added a computed property username which returns this.$route.params.username so we can use:

`<div>{{username}}</div>`

to show the username URL parameter.

We can also have multiple parameters in one route.

For example, we can write the following:

src/index.js :

const Name = {
  template: `<div>
    {{$route.params.firstName}}
    {{$route.params.lastName}}
  </div>`
};

const routes = [{ path: "/name/:firstName/:lastName", component: Name }];

const router = new VueRouter({
  routes
});

new Vue({
  el: "#app",
  router
});

index.html :

<!DOCTYPE html>
<html>
  <head>
    <title>App</title>
    <meta charset="UTF-8" />
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
  </head>
  <body>
    <div id="app">
      <div>
        <router-link to="/name/Jane/Doe">Jane</router-link>
        <router-link to="/name/Mary/Smith">Mary</router-link>
      </div>
      <router-view></router-view>
    </div>
    <script src="src/index.js"></script>
  </body>
</html>

Then when we click on the links, we get the first name and last name that we passed into the URL parameters.

:firstName and :lastName are matched to the params by position.

Reacting to Params Changes

We can watch the $route object to watch for param changes. Routes that the same name but different params use the same components. They won’t be re-rendered from scratch, so the lifecycle hooks won’t be called.

For example, we can write the following:

src/index.js :

const Name = {
  data() {
    return {
      oldName: "",
      newName: ""
    };
  },
  watch: {
    $route(to, from) {
      this.oldName = from.params.name;
      this.newName = to.params.name;
    }
  },
  template: `<div>
    Old: {{oldName}}
    New: {{newName}}
  </div>`
};

const routes = [{ path: "/name/:name", component: Name }];

const router = new VueRouter({
  routes
});

new Vue({
  el: "#app",
  router
});

index.html :

<!DOCTYPE html>
<html>
  <head>
    <title>App</title>
    <meta charset="UTF-8" />
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
  </head>
  <body>
    <div id="app">
      <div>
        <router-link to="/name/Jane">Jane</router-link>
        <router-link to="/name/Mary">Mary</router-link>
      </div>
      <router-view></router-view>
    </div>
    <script src="src/index.js"></script>
  </body>
</html>

In the code above, we have the Name component that’s mapped to a route that takes the name route parameter.

Also, Name has watcher for the $route object that takes the to and from parameters. They are the previous and current routes respectively.

So when we click back and forth between links, we’ll see the old parameter and new parameter displayed.

Catch all / 404 Not found Route

We can add * as a wildcard character for routes.

For example, we can use:

path: '*'

to match all routes and:

path: '/user-*'

to match anything that begins with user- .

For example, we can use the wildcard character as follows:

src/index.js :

const Foo = { template: "<p>foo</p>" };
const Bar = { template: "<p>bar</p>" };
const NotFound = { template: "<p>not found</p>" };
const routes = [
  { path: "/foo", component: Foo },
  { path: "/bar", component: Bar },
  { path: "*", component: NotFound }
];

const router = new VueRouter({
  routes
});

new Vue({
  el: "#app",
  router
});

index.html :

<!DOCTYPE html>
<html>
  <head>
    <title>App</title>
    <meta charset="UTF-8" />
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
  </head>
  <body>
    <div id="app">
      <div>
        <router-link to="/foo">Foo</router-link>
        <router-link to="/bar">Bar</router-link>
      </div>
      <router-view></router-view>
    </div>
    <script src="src/index.js"></script>
  </body>
</html>

When we go to any URL other than /foo or /bar , we’ll see the ‘not found’ message.

We can use the wildcard character with other text as follows:

src/index.js :

const Foo = { template: "<p>foo</p>" };
const Bar = { template: "<p>bar</p>" };
const routes = [
  { path: "/foo*", component: Foo },
  { path: "/bar", component: Bar }
];

const router = new VueRouter({
  routes
});

new Vue({
  el: "#app",
  router
});

index.html :

<!DOCTYPE html>
<html>
  <head>
    <title>App</title>
    <meta charset="UTF-8" />
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
  </head>
  <body>
    <div id="app">
      <div>
        <router-link to="/foo">Foo</router-link>
        <router-link to="/bar">Bar</router-link>
      </div>
      <router-view></router-view>
    </div>
    <script src="src/index.js"></script>
  </body>
</html>

Then we see foo when we go to any URL that starts with foo .

Regular Expressions

We can use regular expressions to match route parameters. For example, we can write:

src/index.js :

const Foo = { template: "<p>foo {{$route.params.id}}</p>" };
const Bar = { template: "<p>bar</p>" };
const routes = [
  { path: "/foo/:id(d+)", component: Foo },
  { path: "/bar", component: Bar }
];

const router = new VueRouter({
  routes
});

new Vue({
  el: "#app",
  router
});

index.html :

<!DOCTYPE html>
<html>
  <head>
    <title>App</title>
    <meta charset="UTF-8" />
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
  </head>
  <body>
    <div id="app">
      <div>
        <router-link to="/foo">Foo</router-link>
        <router-link to="/bar">Bar</router-link>
      </div>
      <router-view></router-view>
    </div>
    <script src="src/index.js"></script>
  </body>
</html>

Then when we go to /foo/1 we see foo 1 . If what comes after /foo/ isn’t a number, then we won’t see anything.

Conclusion

We can pass in route parameters by prefix whatever we want to pass in with a colon, then we can get it from the this.$route.params object.

The asterisk is a wildcard character that matches any URLs that don’t match the routes listed. We can also combine it with other text to match patterns that we want to match.

Finally, we can use regex to match route parameters.