Вероятно, самый простой способ - создать массив всех ваших городов в памяти (select name from cities
), а затем использовать регулярные выражения или простые строковые методы, чтобы увидеть, находятся ли эти города в тексте.
List<string> cities = GetCitiesFromDatabase(); // need to implement this yourself
string text = @"the text containign city names such as Amsterdam and San Francisco";
bool containsACity = cities.Any(city => text.Contains(city)); //To search case insensitive, add StringComparison.CurrentCultureIgnoreCase
IEnumerable<string> containedCities = cities.Where(city => text.Contains(city));
Чтобы гарантировать, что «Амстердам» не будет совпадать с «Амстердамнед», вы можете использовать регулярное выражение вместо Contains:
bool containsACity = cities.Any(city => Regex.IsMatch(text, @"\b"+Regex.Escape(city))+@"\b")
// Add RegexOptions.IgnoreCase for case insensitive matches.
IEnumerable<string> containedCities = cities.Where(city => Regex.IsMatch(text, @"\b"+Regex.Escape(city))+@"\b");
В качестве альтернативы, вы можете построить большойрегулярное выражение для поиска любого города и его однократного выполнения:
string regex = @"\b(?:" + String.Join("|", cities.Select(city => Regex.Escape(city)).ToArray()) + @")\b"
bool containsACity = Regex.IsMatch(text, regex, RegexOptions.IgnoreCase);
IEnumerable<string> containedCities = Regex.Matches(text, regex, RegexOptions.IgnoreCase).Cast<Match>().Select(m => m.Value);
Вы можете улучшить производительность этих вызовов, кэшируя список городов или кэшируя регулярное выражение (и улучшая еще больше, создав статический объект Regex только для чтения с RegexOptions.Compiled ).
Другим решением будет вычисление этого значения в базе данных вместо хранения локального списка городов в памяти, отправка ввода в базу данных и использованиеоператор LIKE или Regex внутри базы данных, чтобы сравнить список городов с текстом.В зависимости от количества городов и размера текста это может быть более быстрым решением, но возможно ли это, зависит от используемой базы данных.