I am opening a URL from javascript. I need to look for the term "colour: x" and then retrieve the value x.
request.get("URL", function (error, res, body)
val = body.indexOf('colour') -> works
which means that web page has the string "colour".
Web page looks like this
size: 8 colour: 1
So, Here I need to retrieve the value of the key 'colour'.
To search for a pattern in any general text:
You can use a regular expression if you know how your information is written.
This regular expression should do the job :
/\bcolour:\s+(\d+)/
(the word "colour:" followed by any space, and then by any number of digits (\d+).
It captures the digits, so this will be the value of the first capture group (found[1]) in my example.
body = `size: 8 colour: 1`
let regex = /\bcolour:\s+(\d+)/;
let found = body.match(regex);
console.log(found[1]);
In the case there is no match (i.e., no 'colour: xx' in the page), the found result will be null, so you should of course check for it before, for safety.
body = `size: 8 but unfortunately, no colour here`
let regex = /\bcolour:\s+(\d+)/;
let found = body.match(regex);
//console.log(found[1]); // Uncaught TypeError: Cannot read property '1' of null
// This snippet below is safe to use :
if (found) {
console.log(found[1]);
} else {
console.log('not found');
}
Related
I have string:
city = 'Hải Phòng'
and an array that I get from an API which looks like this:
data = [{},{},{},{ MaTinhThanh: 'xx', TenTinhThanh: 'Hải Phòng' },{},{}]
I want to find an object in my data:
mycity = data.find( c=>c.TenTinhThanh.includes(city))
the above gives undefined, but I expect
{ MaTinhThanh: 'xx', TenTinhThanh: 'Hải Phòng' }
My API endpoint is:
https://donhang.vnpost.vn/api/api/TinhThanh/GetAll
I am using visual code, Axios, nodejs
I also tried the getting the length of both strings:
data[3].TenTinhThanh.length` ====>11
city.length` ====>9
What is the problem?
Your two strings don't contain the same characters, even though the appear to be visually the same:
const city = "Hải Phòng";
const objV = "Hải Phòng";
console.log(city === objV); // false
This is because you're using the precomposed forms of:
ả (latin small letter a with hook above)
ò (latin small letter o with grave)
in your search string city. These precomposed characters are legacy unicode characters, instead, you should be using the decomposed forms, which are the characters being used in your object value:
ả (latin small letter a a, followed by combining hook above ̉)
ò (latin small letter o o, followed by combining grave accent ̀)
(yes, these are different to the ones listed previously). You can do this by updating your city to hold "Hải Phòng" (which uses the decomposed characters for ả and ò). If you can't decompose your string for whatever reason, you can use String.prototype.normalize() on your input string or your object string, eg:
const city = 'Hải Phòng'.normalize("NFD"); // or just use `const city = "Hải Phòng";`
const data = [{},{},{},{ MaTinhThanh: 'xx', TenTinhThanh: 'Hải Phòng' },{},{}];
const mycity = data.find( c=>c.TenTinhThanh?.includes(city));
console.log(mycity);
Check that the property exists in the first place, then match against that city value. It looks like there may have been something wrong with the encoding of the strings, because I received an error before I copied the city var value to the object.
Edit: It looks like another user laid out this issue in detail.
let city = 'Hải Phòng';
const data = [{},{},{},{ MaTinhThanh: 'xx', TenTinhThanh: 'Hải Phòng' },{},{}];
let mycity = data.find(c => c.TenTinhThanh && c.TenTinhThanh === city);
console.log(mycity);
I have a scenario like Need to edit the single quotes values (only single quotes values),
So I extracted the single quotes values using regex and prepare the reactive dynamic form.
onclick of performing edit button will show old step name above, new step name below, submit step will replace the step name in the original array.
WOrking fine as expected in few scenarios according to my approach, but in scenarios, I realized whatever algorithm I am following does not fulfill my requirement.
Below are the test cases
Test case 1:
Step Name: "Then I should hire an employee using profile '1' for 'USA'",
// Here --> '1', 'USA' values are editable
Test case 2: "And Employee should be hired on '01' day of pay period '01' of 'Current' Fiscal"
// '01', '01', 'Current'
Issues: in test case 2 if I tried to edit second 01 it is editing the first 01
I try to solve the perform edit function with help of indexof, substring functions
this.replaceString = this.selectedStep.name;
this.metaArray.forEach((element: any) => {
var metaIndex = this.replaceString.indexOf(element.paramValue);
if (metaIndex !== -1) {
const replaceValue = this.stepEditForm.controls[element['paramIndex']].value;
this.replaceString = this.replaceString.substring(0, metaIndex) + replaceValue + this.replaceString.substring(metaIndex + (element.paramValue.length));
}
});
but in indexof always find the first occurrence of a value in a string. So I realized my approach is wrong on performed it function
please find the attachment for the code
https://stackblitz.com/edit/angular-reactive-forms-cqb9hy?file=app%2Fapp.component.ts
So Can anyone please suggest to me how to solve this issue,
Thanks in advance
I added a function called matchStartingPositions that returns the starting position indexes of each match. Using this method you can then perform your edit by replacing the string just as you do, but we'll find the proper match to be replaced at the given position.
So in your line
var metaIndex = this.replaceString.indexOf(element.paramValue);
we can then add a second parameter to indexOf, that is the starting point:
var metaIndex = this.replaceString.indexOf(element.paramValue, startingPositions[element.paramIndex]);
The function for getting the index positions just looks for those single quotes in a given string:
matchStartingPositions(str) {
let count = 0;
let indices = [];
[...str].forEach((val, i) => {
if (val === "'") {
if (count % 2 == 0) {
indices.push(i);
}
count++;
}
});
return indices;
}
Here it is in action:
https://angular-reactive-forms-xhkhmx.stackblitz.io
https://stackblitz.com/edit/angular-reactive-forms-xhkhmx?file=app/app.component.ts
I am using indexOf to see if an email contains anything other than a particular text.
For example, I want to check if an email DOES NOT include "usa" after the # symbol, and display an error message.
I was first splitting the text and removing everything before the # symbol:
var validateemailaddress = regcriteria.email.split('#').pop();
Then, I check if the text doesn't include "usa":
if(validateemailaddress.indexOf('usa')){
$('#emailError').show();
}
Something with the above check doesn't seem right. It works - I can enter an email, and if it does not include 'usa', then the error message will show.
Regardless, when I add an additional check, like if the email does not include "can", then the error message shows no matter what.
As follows:
if(validateemailaddress.indexOf('usa') || validateemailaddress.indexOf('can')){
$('#emailError').show();
}
As stated, using the above, the error message will show regardless if the email includes the text or not.
All I want to do is check if the email includes 'usa' or 'can', and if it doesn't, then show the error message.
How can I make this work?
Here is a simple JavaScript function to check if an email address contains 'usa' or 'can'.
function emailValid(email, words) {
// Get the position of # [indexOfAt = 3]
let indexOfAt = email.indexOf('#');
// Get the string after # [strAfterAt = domain.usa]
let strAfterAt = email.substring(indexOfAt + 1);
for (let index in words) {
// Check if the string contains one of the words from words array
if (strAfterAt.includes(words[index])) {
return true;
}
}
// If the email does not contain any word of the words array
// it is an invalid email
return false;
}
let words = ['usa', 'can'];
if (!emailValid('abc#domain.usa', words)) {
console.log("Invalid Email!");
// Here you can show the error message
} else {
console.log("Valid Email!");
}
You can do something like that, using includes:
const validateEmailAdress = (email) => {
const splittedEmail = email.split('#').pop();
return (splittedEmail.includes('usa') || splittedEmail.includes('can'))
}
console.log("Includes usa: ", validateEmailAdress("something#gmail.usa"))
console.log("Includes can: ", validateEmailAdress("something#gmail.can"))
console.log("Does not includes: ", validateEmailAdress("something#gmail.com"))
There are several ways to check, if a string contains/does not contain a substring.
String.prototype.includes
'String'.includes(searchString); // returns true/false
String.prototype.indexOf
// returns values from -1 to last postion of string.
'String'.indexOf(searchString);
// In combination with ~ this can work similar to includes()
// for strings up to 2^31-1 byte length
// returns 0 if string is not found and -pos if found.
~'String'.indexOf(searchString);
With the help of Regular Expressions:
// substring must be escaped to return valid results
new RegExp(escapedSearchString).test('String'); // returns true/false if the search string is found
'String'.match(escapedSearchString); // returns null or an array if found
So overall you can use allmost all methods like:
if ('String'.function(searchString)) {
// 'String' includes search String
} else {
// 'String' does not include search String
}
Or in case of indexOf:
if ('String'.indexOf(searchString) > -1) {
// 'String' includes search String
} else {
// 'String' does not include search String
}
// OR
if (~'String'.indexOf(searchString)) {
// 'String' includes search String
} else {
// 'String' does not include search String
}
I believe this regular expression match is what you're looking for
System.out.println(myString.matches("(.)#(.)usa(.*)"));
I have a url with format like this:
http://www.test.com/document/navigate/{{project_id}}/{{note_id}}
the value within {{}} will be filled with integer, like this for example
http://www.test.com/document/navigate/1/3
http://www.test.com/document/navigate/7/2
http://www.test.com/document/navigate/3
the value for note_id in the url is not mandatory, but i need to retrieve both for the project_id and note_id. how can i achieve that?
You can use a regular expression: http[s]?:\/\/www.test.com\/document\/navigate\/([\d]+)[\/]?([\d]+)?[\/]?.
Essentially it is laying out the protocol, hostname/domain, and the part of the path that we know. Then there are two capturing groups - the project ID and the note ID (optional).
You could use it like so:
const url = 'http://www.test.com/document/navigate/1/3';
const parts = url.match(/http[s]?:\/\/www.test.com\/document\/navigate\/([\d]+)[\/]?([\d]+)?/);
console.log(parts[0]); // "http://www.test.com/document/navigate/1/3" <- full match
console.log(parts[1]); // "1" <- first group
console.log(parts[2]); // "3" <- second group, which will be undefined if left off
Note: this may not be a foolproof answer. I recommend trying out many other potential variations. Also be aware that this returns strings, so you may have to parseInt() or something if you want real numbers.
Here is a Regexr showing you how this works (this is how I mess around until I get it right).
One way you can make use of the part navigate/ like the following way:
var url1 = 'http://www.test.com/document/navigate/1/3';
var url2 = 'http://www.test.com/document/navigate/7/2';
var url3 = 'http://www.test.com/document/navigate/3';
function getValue(url){
var arr = url.match(/navigate\/([^ ]*)/);
arr = arr[arr.length - 1].split('/');
if(arr.length == 1)
return { project_id: +arr[0] };
else if(arr.length == 2)
return { project_id: +arr[0], note_id: +arr[1] };
else
return 'invalid';
}
console.log(getValue(url1));
console.log(getValue(url2));
console.log(getValue(url3));
Aanval op Vlemis (499|453) C44
This is what the string looks like. Though it's actually like this: "Aanval op variable (variable) variable
What I want to do is 1: get the coordinates (I already have this), 2 get Vlemis (first variable), get C44 (third variable) and check to see if the string is of this type.
My code:
$("#commands_table tr.nowrap").each(function(){
var text = $(this).find("input[id*='editInput']").val();
var attackername= text.match(/(?=op)[\s|\w]*(?=\()/);
var coordinates = text.match(/\(\d{1,3}\|\d{1,3}\)/);
});
Coordinates works, attackername however doesn't.
Html:
<span id="labelText[6]">Aanval op Vlemis (499|453) C44</span>
You should use one regex to take everything :
var parts = text.match(/(\w+)\s*\((\d+)\|(\d+)\)\s*(\w+)/).slice(1);
This builds
["Vlemis", "499", "453", "C44"]
If you're not sure the string is valid, test like this :
var parts = text.match(/(\w+)\s*\((\d+)\|(\d+)\)\s*(\w+)/);
if (parts) {
parts = parts.slice(1);
// do things with parts
} else {
// no match, yell at the user
}