C# Поиск строк в текстовом файле по ключевому слову
Всем привет. У меня есть текстовый файл, в котором написано id города и сам город через запятую. Пример:
1241,Moscow
1232,Sankt-Peterburg
1421,Ekateriburg
1314,Prosekatir
1412,Alexandria ...
Мне нужно с помощью ключевого слова (Например, ekat) найти все строки, которые имеют это ключевое слово. И получить:
1421,Ekateriburg
1314,Prosekatir
Пытался сделать это с помощью такого кода:
string keyWord = countryTextBox.Text;
string str = File.ReadAllText(Application.StartupPath + "/city.txt");
var kek = str.Split(new Char[] { ' ', '.', ',', ':'}).ToList();
foreach (string s in kek)
{
if (s.Trim() != "" && Regex.IsMatch(s, keyWord))
{
MessageBox.Show(kek[kek.IndexOf(keyWord) + 1] + " " + kek[kek.IndexOf(keyWord) + 3], "Найденные ID по ключевому слову", MessageBoxButtons.OK, MessageBoxIcon.Information);
break;
}
}
Но он выводит только часть и не совсем правильную:
Ekateriburg
1314,Prosekatir
1412
Ответы (3 шт):
Для удобства создайте класс, который будет содержать в себе ID и название:
class City
{
public City(int id, string name)
=> (Id, Name) = (id, name);
public int Id { get; }
public string Name { get; }
}
Далее прочитайте все построчно из файла и заполните список:
var list = File.ReadAllLines("Test.txt").Select(x => x.Split(',')).Select(x => new City(int.Parse(x[0]), x[1]));
Ну а дальше делайте поиск чего вам надо:
var result = list.Where(x => x.Name.Contains("ekat"));
В результате вы получите один объект: 1314,Prosekatir. Если надо еще захватить и Ekateriburg, то приводите все в нижний регистр (Where(x => x.Name.ToLower().Contains("ekat"))).
var lines = File.ReadLines(Application.StartupPath + "/city.txt");
string result = string.Join("\n",
lines.Where(s => s.IndexOf(keyword, StringComparison.InvariantCultureIgnoreCase) >= 0));
MessageBox.Show(result, "Найденные ID по ключевому слову");
Неплохой вопрос для практики алгоритмов.
Там понадобится простая структура данных - Trie. Это по сути обычное дерево, где связи между узлами представлены символами.
class TrieNode
{
private HashSet<int> _cities = new HashSet<int>();
private Dictionary<char, TrieNode> _children = new Dictionary<char, TrieNode>();
public void Add(int id, string city, int index = 0)
{
if (index >= city.Length) return;
_cities.Add(id);
var c = city[index];
if (!_children.ContainsKey(c)) _children[c] = new TrieNode();
TrieNode child = _children[c];
child.Add(id, city, index+1);
}
public IEnumerable<int> GetCities(string prefix, int index = 0)
{
if (index == prefix.Length) return _cities;
if (_children.ContainsKey(prefix[index]))
return _children[prefix[index]].GetCities(prefix, index+1);
return Enumerable.Empty<int>();
}
}
Теперь можно считать все города из файла
var fname = @"D:\temp\SO\1099753\sample.txt";
var citiesById = File.ReadAllLines(fname)
.Select(x => x.Split(','))
.Select(x => (int.Parse(x[0]), x[1]))
.ToDictionary(x=>x.Item1, x=>x.Item2);
После создадим корневой узел и закинем туда все города, включая все постфиксы городов
var root = new TrieNode();
foreach(var cityWithId in citiesById)
for(int i=0; i<cityWithId.Value.Length; i++)
root.Add(cityWithId.Key, cityWithId.Value.ToLowerInvariant(), i);
Поиск становится шустрым и несложным делом
Console.WriteLine("ekat cities:");
foreach (var cityId in root.GetCities("ekat"))
Console.WriteLine(citiesById[cityId]);
Console.WriteLine();
Console.WriteLine("os cities:");
foreach (var cityId in root.GetCities("os"))
Console.WriteLine(citiesById[cityId]);
Вывод
ekat cities:
Ekateriburg
Prosekatir
os cities:
Moscow
Prosekatir