Viju
Viju

Reputation: 427

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?

Upvotes: 4

Views: 1109

Answers (6)

Inspiraller
Inspiraller

Reputation: 3806

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);
}

Upvotes: 0

Alberto De Caro
Alberto De Caro

Reputation: 5213

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.

Upvotes: 1

Eric Leroy
Eric Leroy

Reputation: 1836

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/

Upvotes: 1

Kailash Yadav
Kailash Yadav

Reputation: 1930

$("#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

Upvotes: 1

jahroy
jahroy

Reputation: 22692

I think you want to accomplish this in a few simple steps:

  1. Split each string in your array before and after the first parenthesis

  2. Apply your first regex to the first part of the string. Store the result as a boolean variable, perhaps named matchOne

  3. 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.

  4. Test if either of the two mathes succeeded: return ( matchOne || matchTwo );

Upvotes: 0

Tim Pietzcker
Tim Pietzcker

Reputation: 336158

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 :)

Upvotes: 2

Related Questions