Day 12. Regular Expressions_Exercise


Level 1 / Level 2 / Level 3

👟Level 1.

1. Calculate the total annual income of the person from the following text.
const txt = 'He earns 4000 euro from salary per month, 10000 euro annual bonus, 5500 euro online courses per month.'
const pattern = /\d+/g;
const matches = txt.match(pattern);
console.log(matches); // (3) ['4000', '10000', '5500']

let [perMonth1, annualBonus, perMonth2] = matches;
let annualIncome = (+perMonth1 + +perMonth2) * 12 + +annualBonus;
console.log(annualIncome);  // 124000

Notice that the matches array has string elements. So to actually calculate the salary, I should convert those strings into numbers. I can use parseInt() or Number() in the place of +. To use the matched values for calculation, I destructured the matched array into three different variables.

2. The position of some particles on the horizontal x-axis -12, -4, -3 and -1 in the negative direction, 0 at origin, 4 and 8 in the positive direction. Extract these numbers and find the distance between the two furthest particles.
const txt = 'The position of some particles on the horizontal x-axis -12, -4, -3 and -1 in the negative direction, 0 at origin, 4 and 8 in the positive direction.';
const pattern = /.\d+/g;
const points = txt.match(pattern);

const sortedPoints = [];
for (let element of matches) {
  element = Number(element);
  sortedPoints.push(element);
}

const distance = sortedPoints[points.length - 1] - sortedPoints[0];

/* using Math methods
const distance = Math.max(...sortedPoints) - Math.min(...sortedPoints);
*/

console.log(points);  // ['-12', '-4', '-3', '-1', ' 0', ' 4', ' 8']
console.log(sortedPoints);  // [-12, -4, -3, -1, 0, 4, 8]

console.log(distance);  // 20

I used . to also extract ‘-‘ in front of each numbers. From the text, the numbers were already sorted so I didn’t have to sort them again. If the numbers are mixed, I can use sort() like below:

sortedPoints.sort((a, b) => a - b);


3) Write a pattern which identifies if a string is a valid JavaScript variable.

A variable name is invalid when:

  • it begins with a number

  • it has special characters except dollar sign($) and underscore(_)

  • it has a space between words

function is_valid_variable(str) {
  const pattern1 = /^\d/;
  const pattern2 = /[^A-Za-z0-9$_]/;
  bool1 = pattern1.test(str);
  bool2 = pattern2.test(str);
  if (bool1||bool2) {
    return 'Invalid';
  } else {
    return 'Valid';
  }
}

console.log(is_valid_variable('first_name'));  // Valid
console.log(is_valid_variable('first-name'));  // Invalid
console.log(is_valid_variable('1first_name'));  // Invalid
console.log(is_valid_variable('firstname'));  // Valid
console.log(is_valid_variable('first name'));  // Invalid

pattern1 checks if the name starts with number. pattern2 checks if the name includes other characters than alphabets, numbers, and special characters that are allowed($ and _). It will also return ‘Invalid’ to a variable name which has space in it. If at least one pattern matches the variable name(and returns true), it is invalid variable.

👟Level 2.

1. Write a function called tenMostFrequentWords which get the ten most frequent word from a string?
  • Similar Task at Day 2

  • Expected output: ``` console.log(tenMostFrequentWords(paragraph)); [ {word:’love’, count:6}, {word:’you’, count:5}, {word:’can’, count:3}, … {word:’If’,count:1} ]

console.log(tenMostFrequentWords(paragraph, 3));

[ {word:’love’, count:6}, {word:’you’, count:5}, {word:’can’, count:3} ]


```js
const paragraph = `I love teaching. If you do not love teaching what else can you love. I love Python if you do not love something which can give you all the capabilities to develop an application what else can you love.`

function tenMostFrequentWords(str, number) {
  const pattern = /[^A-Za-z ]/g;
  const onlyWords = str.replace(pattern, '');
  const wordIndex = [...new Set(onlyWords.split(' '))];
  const wordsAndCounts = [];
  for (i = 0; i < wordIndex.length; i++) {
    let word = new RegExp(`${wordIndex[i]}`, 'g');
    wordsAndCounts[i] = {word: wordIndex[i], count: onlyWords.match(word).length}
  }
  const sortedWordCounts = wordsAndCounts.sort((a, b) =>
    b.count - a.count
  );
  const printOut = sortedWordCounts.filter((object) =>
    sortedWordCounts.indexOf(object) < number);
  return printOut;
}

console.log(tenMostFrequentWords(paragraph, 10));

To only extract word characters, I removed all the characters except A-Z and a-z, and space by using replace() method. Then I splitted the onlyWords string by a space, and used Set() to get the index of words.

I have to put new in the front when using Set or RegExp.

To put a variable as a regular expression, I must use RegExp constructor. Using string templates(${}) without using the constructor wouldn’t work.

// it returns null
let matches = /${wordIndex[i]}/g
  wordsAndCounts[i] = {word: wordIndex[i], count: onlyWords.match(matches).length}


  • Mistakes I’ve been through

1) I first declared the wordsAndCounts array inside the for loop, and an empty array was returned when I logged the array to console. Because I declared the array with const, it wouldn’t change unless I move the array to the outside of the loop.

2) Again, when using higher order functions, if the statement is single lined, I shouldn’t use curly braces. Otherwise, the function wouldn’t be executed.

👟Level 3.

1. Write a function which cleans the following text(remove all punctuations). After cleaning, count three most frequent words in the string.
const sentence = '%I $am@% a %tea@cher%, &and& I lo%#ve %tea@ching%;. There $is nothing; &as& mo@re rewarding as educa@ting &and& @emp%o@wering peo@ple. ;I found tea@ching m%o@re interesting tha@n any other %jo@bs. %Do@es thi%s mo@tivate yo@u to be a tea@cher!?'

// cleaning the text
function cleanText(str) {
  const pattern = /[^A-Za-z ]/g;
  const cleanedText = str.replace(pattern, '');
  return cleanedText;
}
console.log(cleanedText);
// I am a teacher and I love teaching There is nothing as more rewarding as educating and empowering people I found teaching more interesting than any other jobs Does this motivate you to be a teacher


// counting three most frequent words in the string
function mostFrequentWords(str) {
  const cleanedText = cleanText(str);
  const wordIndex = [...new Set(cleanedText.split(' '))];
  const wordsAndCounts = [];
  for (i = 0; i < wordIndex.length; i++) {
    let word = new RegExp(`${wordIndex[i]+ ' '}`, 'g');
    wordsAndCounts[i] = { word: wordIndex[i], count: cleanedText.match(word).length };
  }
  const sortedWordCounts = wordsAndCounts.sort((a, b) =>
    b.count - a.count
  );
  const printOut = sortedWordCounts.filter((object) =>
    sortedWordCounts.indexOf(object) < 3);
  return printOut;
}

console.log(mostFrequentWords(sentence));
/* (3)[
  {word: 'I', count: 3},
  {word: 'a', count: 2},
  {word: 'and', count: 2}] */


  • Mistakes I’ve been through

The function first returned {word: ‘a’, count: 16} as the most frequent language. I guess the match() searched all the single character ‘a’s in the sentence. So I had to find a way to put a variable into regular expression, and to find an exact match.

First I tried to use ^...$, but I couldn’t find how to put these anchors in RegExp constructor. I finally figured out how. Since I was matching each unique words with the cleanedText, I had to add a space(‘ ‘) to only extract the exact ‘a’. At the beginning I wrote like below:

let word = new RegExp(`${wordIndex[i] }`, 'g');

I thought just adding a space inside the string template would be fine, but it didn’t work. So I used a plus sign to explicitly add a space in a pattern, and it worked.

let word = new RegExp(`${wordIndex[i] + ' '}`, 'g');


Leave a comment