extract city name from a string with node - javascript

My script receive a string from the user that contains city name or more than one, I want to extract the city name. My current code split the string to words based on white space but if the city name is two words that will not work.
I can have an array of expected city names and I want to match the city name of the string against that array, is there any possible way without having to use neural language processing techniques ??
Example
var cities = ['Cairo', 'Dubai', 'San Francisco']
// possible strings
var user_string = 'traveling to Cairo' // result ['Cairo']
var user_string = 'will leave San Francisco to Dubai late' // result ['San Francisco', 'Dubai']

Create a RegExp and use match
user_string.match(new RegExp( cities.join("|"), "gi" ) )
Demo
var fnMatches = ( cities, str ) => str.match(new RegExp( cities.join("|"), "gi" ) );
var cities = ['Cairo', 'Dubai', 'San Francisco'];
console.log( fnMatches( cities, "traveling to Cairo" ) );
console.log( fnMatches( cities, "will leave San Francisco to Dubai late" ) );

You should use regular expressions to match the cities
for(i=0; i < cities.length; i++) {
if(user_string.match(new RegExp(cities[i], 'i'))){
console.log(cities[i]);
}
}

Related

Regex to remove London except London City

I need to write a regex to remove London from the list except London City. Thanks in advance.
Input
London Heathrow, London Gatwick, London City, London Southend, London Stanstead
Output
Heathrow, Gatwick, London City, Southend, Stanstead
Use replace() method with negative look ahead assertion regex.
var str = 'London Heathrow, London Gatwick, London City, London Southend, London Stanstead';
console.log(
str.replace(/\bLondon\s(?!City\b)/gi, '')
)
Regex explanation here.
Your regex would be
/London City|London\s/g
Match London City first and then London and then in the matcher callback method replace based on matched value
try this as well
var input = "London Heathrow, London Gatwick, London City, London Southend, London Stanstead";
var output = input.replace(/London City|London\s/g, function(match){if (match == "London City") { return match } else { return "" }} );
console.log(output);
You can extend this regex to include other names as well (which you don't want to be replaced), for example
/London Heathrow|London City|London\s/g //would not replace London Heathrow and London City
You can make it more dynamic by using a regex constructor as
var itemsNotToBeReplaced = ["London Heathrow", "London City"];
var regex = new RegExp( itemsNotToBeReplaced.push("London\s").join("|"), "g" );
input.replace(regex , function(match){
if (itemsNotToBeReplaced.indexOf(match) != -1)
{
return match ;;
}
else
{
return "" ;
}
});

How to Skip Over Word in Loop in Javascript

I have the following strings:
str=["If we go to the park, we will find a big slide!"];
replacer=[["to","a"],["a","un"]];
I then iterate through str and replace each occurrence of "to" with "a" and then each occurrence of "a" with "un" and end up with:
str=["If we go un the park, we will find un big slide!"];
I understand that in this simple case I could reverse the replacer values but that is not an option for me. Is there anyway I could put some kind of disclaimer or flag with the replaced word so that when I iterate through for the next variable it skips the already replaced word?
Thanks!
try
var str=["If we go to the park, we will find a big slide!"];
function replacer(str, oldarr, newArr)
{
oldarr.forEach( function(value,index){
str = str.replace( new RegExp(value, "g"), newArr[index] );
} );
return str;
}
replacer(str[0],["to","a"],["a","un"]);
You can split str by space to array, and then iterate over each word, saving "used" index to temporary array not to overwrite it again, then join this array back to string:
var str = ["If we go to the park, we will find a big slide!"];
var replacer = [["to","a"],["a","un"]];
var ar = str[0].split(' ');
var used = [];//temporary array to hold indexes of changes values
replacer.forEach(function(v,k){
ar.forEach(function(x,i){
if(used.indexOf(i) < 0){
if(x == v[0]){
ar[i] = v[1];
used.push(i);
}
}
});
});
str = [ar.join(' ')];
console.log(str);
Output:
["If we go a the park, we will find un big slide!"]

Getting Rid of Extraneous Characters in a String-Javascript

I am loading data about NBA games from an API using Javascript, and I want to manipulate it but am having trouble. Each game is its own separate object, and is the data is returned like this:
Date: "Nov 7, 2014"
Opponent: "# Charlotte"
Result: "L"
Score: "122-119"
Spread: "+1.5"
Depending on whether the team is home or away, there is either a "#" or a "vs" in front of the name of the opponent for that particular game. I want to get rid of this, so that the "Opponent" key only has "Charlotte" as its value in the above example.
I've tried usinggameLog[i].Opponent = (gameLog[i].Opponent.split(" ").pop
to get rid of any characters before the space, but this ruins the data when there is a team name with a space in it like "New York" or "Los Angeles"
This takes the string, and creates a new substring starting at the index of the first white space. e.g.:
# New York = a new string starting after the #. -> New York
gameLog[i].Opponent = gameLog[i].Opponent.substr(gameLog[i].Opponent.indexOf(' ')+1);
I guess, something along these lines might help.
var home = "# Charlotte";
var opponent = "vs New York";
function parse(team){
// Case when it is a home team
if ( team.indexOf("#") === 0 ){
return team.replace("#","").trim();
// Away team
} else {
return team.replace("vs","").trim();
}
}
console.log( parse(home) );
console.log( parse(opponent) );
gameLog[i].Opponent = (gameLog[i].Opponent.split(" ").slice(1).join(" "));
Split based off space character
Slice off the first item in the array
Join the contents of the array back together with space.
You can use regular expressions to replace unwanted characters while looping over an array of objects.
for (var i = 0; i < arr.length; i++) {
arr[i].Opponent = arr[i].Opponent.replace(/#\s|vs\s/g, '');
}
Here's a jsbin
You need the substr() method:
var str = "# Charlotte";
var res = str.substr(2);
Result: Charlotte
Unless there is also a space after "vs", which is not clear.
Then you could use:
var str = "# Charlotte";
var res = str.substr(str.indexOf(' ')+1);

Jquery Autocomplete custom return data

Hello i'm using Jquery autocomplete for a project but i've a particular problem with my language. Here in albania our alphabet includes characters like ë and ç but some people don't know keyboard combination to produce this character and i'm trying to return these words using 'e' and 'c'. Example when people search for 'Dhermi' i want to show the word 'Dhërmi' as a suggestions. Same for the word "canta" i want to show "çanta". Here are many words like these so i want a function to return data in this way.
Below is my function
$("#search").autocomplete({
minLength:0,
delay:10,
appendTo: ".search",
source:function(request, response) {
//
var matchernormal = new RegExp( "^" + $.ui.autocomplete.escapeRegex( request.term ), "i" );
matcher = $.grep(tagsarr, function( item ){return matchernormal.test(item);})
console.log(matcher)
// Limit Results
var results = $.ui.autocomplete.filter(matcher, request.term);
response(results.slice(0, 10));
}
});
I'll be grateful if someone could help me with this problem that i've encountered.
What you are looking for is accent folding:
https://jqueryui.com/autocomplete/#folding
you can have a map of the accent characters to the normalised characters
var accentMap = {
"á": "a",
"ö": "o"
};
and a function to convert one from other (see the example link)
var normalize = function( term ) {....}
and compare with the normalised value of the string as well as the original one:
return matcher.test( value ) || matcher.test( normalize( value ) );

javascript regular expression matching cityname

I have the following array of data named cityList:
var cityList = [
"Anaa, French Polynesia (AAA)",
"Arrabury, Australia (AAB)",
"Al Arish, Egypt (AAC)",
"Ad-Dabbah, Sudan (AAD)",
"Annaba, Algeria (AAE)",
"Apalachicola, United States (AAF)",
"Arapoti, Brazil (AAG)",
"Aachen, Germany (AAH)",
"Arraias, Brazil (AAI)",
"Awaradam, Suriname (AAJ)",
"Aranuka, Kiribati (AAK)",
"Aalborg, Denmark (AAL)"
];
I want to first search the city name starting at the beginning of the string.
Next I want to search the code portion of the string: AAA, AAB, AAC, etc...
I want to apply a search pattern as a javascript regular expression, first to the city name, and second to the city code.
Here are my regular expressions:
// this regular expression used for search city name
var matcher = new RegExp("^" + re, "i");
// this regular expression used for search city code
var matcher = new RegExp("([(*)])" + re, "i");
How do I combine these two regular expressions into a single regex that works as described?
I suggest this:
var myregexp = /^([^,]+),[^(]*\(([^()]+)\)/;
var match = myregexp.exec(subject);
if (match != null) {
city = match[1];
code = match[2];
}
Explanation:
^ # Start of string
( # Match and capture (group number 1):
[^,]+ # One or more characters except comma (alternatively insert city name)
) # End of group 1
, # Match a comma
[^(]* # Match any number of characters except an opening parenthesis
\( # Match an opening parenthesis
( # Match and capture (group number 2):
[^()]+ # One or more characters except parentheses (alt. insert city code)
) # End of group 2
\) # Match a closing parenthesis
This assumes that no city name will ever contain a comma (otherwise this regex would only capture the part before the comma), so you'd need to check your data if that's ever possible. I can't think of an example, but that's not saying anything :)
$("#leavingCity").autocomplete({
source: function(req, responseFn) {
var re = $.ui.autocomplete.escapeRegex(req.term);
var matcher = new RegExp("/^([^,]+),[^(]*\(([^()]+)\)/", "g");
var a = $.grep(cityList, function(item,index) { return matcher.test(item); });
responseFn(a);
} });
Try this, regualr expression by Tim Pietzcker
This is the most elegant way I can do it:
var cityList = ["Anaa, French Polynesia (AAA)","Arrabury, Australia (AAB)","Al Arish, Egypt (AAC)","Ad-Dabbah, Sudan (AAD)","Annaba, Algeria (AAE)","Apalachicola, United States (AAF)","Arapoti, Brazil (AAG)","Aachen, Germany (AAH)","Arraias, Brazil (AAI)","Awaradam, Suriname (AAJ)","Aranuka, Kiribati (AAK)","Aalborg, Denmark (AAL)"];
var regex = /([a-z].+?),.+?\(([A-Z]{3,3})\)/gi, match, newList = [];
while (match = regex.exec(cityList)) {
newList.push(match[1]+" - "+match[2]);
}
alert(newList[7]);
// prints Aachen - AAH
If you don't understand how to use parentheses in your regex, I suggest you check out the site I learned from: http://www.regular-expressions.info/
Here I suggest a completly different approach (ECMA-262 standard).
As using the regex requires a linear search anyway, if you can pre-process the data, you can set up an array of city objects:
function City(name, country, code){
this.cityName = name;
this.cityCountry = country;
this.cityCode = code;
}
var cities = [];
cities.push(new City('Anaa', 'French Polynesia', 'AAA'));
// ... push the other cities
And a search function:
function GetCity(cityToSearch, cities){
var res = null;
for(i=0;i<cities.length;i++){
if(cities[i].city = cityToSearch
res = cities[i];
}
return res;
}
At run time:
var codeFound = '';
var cityFound = GetCity('Arraias');
if(cityFound != null)
codeFound = cityFound.cityCode;
Remark
In both case, if you are going to fill the cities array with all city of the world, the city name is not a key! For instance there are half a dozen of 'Springfield' in USA. In that case a better approach is to use a two-fields key.
I think you want to accomplish this in a few simple steps:
Split each string in your array before and after the first parenthesis
Apply your first regex to the first part of the string. Store the result as a boolean variable, perhaps named matchOne
Apply your second regex to the second part of the string (don't forget to remove the closing parenthesis). Store the result as a boolean variable, perhaps named matchTwo.
Test if either of the two mathes succeeded: return ( matchOne || matchTwo );
Use indexOf
Its more efficient and explicit of expectation. regex is unnecessary.
const isMatchX = cityList.indexOf('AAB');
const isMatchY = cityList.indexOf('Awar');
Alternatively you could so something like this but its way overkill when you can use indexOf:
const search = (cityList, re) => {
const strRegPart1 = "¬[^¬]*" + re + "[^¬]*";
const strRegPart2 = "¬[^¬]*\\([^\\)]*" + re + "[^\\)]*\\)($|¬)";
const regSearch = RegExp("(" + strRegPart1 + "|" + strRegPart2 + ")", "gi");
const strCityListMarked = '¬' + cityList.join('¬');
const arrMatch = strCityListMarked.match(regSearch);
return arrMatch && arrMatch[1].substr(1);
}

Categories

Resources