用c#在txt文件中搜索字符串

Search for strings in a txt file with c#

我正在执行一项任务,该任务将显示有多少国家在 2004 年加入了欧盟。 我还想收到 2004 年加入的国家的名称。我开始做我的工作,但我只收到塞浦路斯。 问题是有几个国家在 2004 年加入了。 如何获取2004年加入的所有国家名称? 我在控制台应用程序 (.NET Framework) 中完成了我的任务。 对于该任务,我使用了一个包含数据的 txt 文件。 这是我的代码:

  class Program
    {
        static List<Country> joining = new List<Country>(); 
        static void read()
        {
            string[] rows=File.ReadAllLines("EU.txt");
            foreach (var item in rows)
            {
                joining.Add(new Country(item));
            }
        }
        
        static void Main(string[] args)
        {
            read();
            
            
            
            // how many countries:
            Console.WriteLine($"{joining.Count(item =>item.date.Split('.')[1] == "05" )}countries joined.");
            //names:
            Console.WriteLine($"Country names:{joining.Find(item =>item.date.Split('.')[1] == "05" ).name}"); // !!! this code is bad

    
            Console.ReadKey();
        }
    }

    class Country
    {
        //Fields
        public string date, name;

        //ctor
        public Country(string row)
        {
            name=row.Split(';')[0];
            date = row.Split(';')[1];
        }
    }

EU.txt:

Austria;1995.01.01
Belgium;1958.01.01
Bulgaria;2007.01.01
Cyprus;2004.05.01
Czech;2004.05.01
Denmark;1973.01.01
United Kingdom;1973.01.01
Estonia;2004.05.01
Finland;1995.01.01
France;1958.01.01
Greece;1981.01.01
Netherlands;1958.01.01
Croatia;2013;07.01
Ireland;1973.01.01
Poland;2004.05.01
Latvia;2004.05.01
Lithuania;2004.05.01
Luxemburg;1958.01.01
Hungary;2004.05.01
Malta;2004.05.01
Germany;1958.01.01
Italy;1958.01.01
Portugal;1986.01.01
Romania;2007.01.01
Spain;1986.01.01
Sweden;1995.01.01
Szlovakia;2004.05.01
Szlovenia;2004.05.01

好吧,joining.Find(...) 只会找到 第一个 项(在您的情况下是 Cyprus)。您可以改用 Linq Where。请注意,您应该比较 "2004"(年),而不是 "05"(月):

  using System.Linq;

  ...

  // names:
  var names = joining
    .Where(item => item.date.Split('.')[0] == "2004")
    .Select(item => item.name);  

  // let's join all the names by ", ":
  Console.WriteLine($"Country names:{string.Join(", ", names)}"); 

编辑: 然而,像item.date.Split('.')[1] == "2004"这样的比较看起来很难看(我为什么要在strings上查询日期?)。 让 Country class 帮助自己(日期、姓名等):

class Country {
    public string Name {get;}
    public DateTime JoinedDate {get;}

    public Country(string row) {
      if (row == null)
        throw new ArgumentNullException(nameof(row));  

      string[] items = row.Split(';', 2);

      if (items.Length < 2)
        throw new FormatException("Invalid row format"); 

      Name = items[0];
      JoinedDate = DateTime.ParseExact(items[1], "yyyy.M.d");
    }

    public override string ToString() => Name;
}

然后就是Linq(我们查询EU.txt文件):

static void Main(string[] args) {
  List<Country> joined2004 = File
    .ReadLines("EU.txt")
    .Select(line => new Country(line))
    .Where(country => country.JoinedDate.Year == 2004)
    .ToList();

  Console.WriteLine($"{joined2004.Count} countries joined.");
  Console.WriteLine($"{string.Join(", ", joined2004)}")  
}

这里有很多小变化:

class Program
{
    static List<Country> Countries; 

    // Use types and methods that avoid needing to load full sets into RAM all at once
    // for as long as possible. That means IEnumerable rather than List and ReadLines() 
    // rather than ReadAllLines().
    // It's also better for the read() function accept a value and return the result
    static IEnumerable<Country> ReadCountries(string filePath)
    {
        // No need to allocate so much RAM via ReadAllLines()
        // Better to just have one line in RAM at a time until everything is loaded
        return File.ReadLines(filePath)
                   .Select(line => new Country(line));
    }
    
    static void Main(string[] args)
    {
        Countries = ReadCountries("EU.txt").ToList();
        var JoinedIn2004 = Countries.Where(c => c.date.Year == 2004);            
        
        Console.WriteLine($"{JoinedIn2004.Count()} countries joined.\nCountry name:");
        // need to loop through the list to get all the names
        foreach(var country in JoinedIn2004)
        {
           Console.WriteLine(country.name); 
        }
        // Alternatively, if you really don't want to write a loop:
        // Console.WriteLine(string.Join("\n", JoinedIn2004));

        Console.ReadKey(true);
    }
}

class Country
{
    // properties > fields
    public string name {get;set;}
    public DateTime date {get;set;} //Parse an actual DateTime for this!
    
    //personally I lean towards a static builder method (Country.FromTextLine())
    // for this, to decouple building the type from any specific file,
    // but I also get it's overkill here.
    public Country(string row)
    {
        var format = "yyyy.MM.dd";
        var fields = row.Split(';');

        name = fields[0];
        date = DateTime.ParseExact(fields[1], format, null);
    }
}
    List<Country> result = joining.FindAll(item =>item.date.Split('.')[1] == "05");
    Console.Write($"Country names:");
    foreach(Country country in result)
    {
        Console.Write($"{country.name} ");
    }
    Console.WriteLine();